PNG  IHDRX cHRMz&u0`:pQ<bKGD pHYsodtIME MeqIDATxw]Wug^Qd˶ 6`!N:!@xI~)%7%@Bh&`lnjVF29gΨ4E$|>cɚ{gk= %,a KX%,a KX%,a KX%,a KX%,a KX%,a KX%, b` ǟzeאfp]<!SJmɤY޲ڿ,%c ~ع9VH.!Ͳz&QynֺTkRR.BLHi٪:l;@(!MԴ=žI,:o&N'Kù\vRmJ雵֫AWic H@" !: Cé||]k-Ha oݜ:y F())u]aG7*JV@J415p=sZH!=!DRʯvɱh~V\}v/GKY$n]"X"}t@ xS76^[bw4dsce)2dU0 CkMa-U5tvLƀ~mlMwfGE/-]7XAƟ`׮g ewxwC4\[~7@O-Q( a*XGƒ{ ՟}$_y3tĐƤatgvێi|K=uVyrŲlLӪuܿzwk$m87k( `múcE)"@rK( z4$D; 2kW=Xb$V[Ru819קR~qloѱDyįݎ*mxw]y5e4K@ЃI0A D@"BDk_)N\8͜9dz"fK0zɿvM /.:2O{ Nb=M=7>??Zuo32 DLD@D| &+֎C #B8ַ`bOb $D#ͮҪtx]%`ES`Ru[=¾!@Od37LJ0!OIR4m]GZRJu$‡c=%~s@6SKy?CeIh:[vR@Lh | (BhAMy=݃  G"'wzn޺~8ԽSh ~T*A:xR[ܹ?X[uKL_=fDȊ؂p0}7=D$Ekq!/t.*2ʼnDbŞ}DijYaȲ(""6HA;:LzxQ‘(SQQ}*PL*fc\s `/d'QXW, e`#kPGZuŞuO{{wm[&NBTiiI0bukcA9<4@SӊH*؎4U/'2U5.(9JuDfrޱtycU%j(:RUbArLֺN)udA':uGQN"-"Is.*+k@ `Ojs@yU/ H:l;@yyTn}_yw!VkRJ4P)~y#)r,D =ě"Q]ci'%HI4ZL0"MJy 8A{ aN<8D"1#IJi >XjX֔#@>-{vN!8tRݻ^)N_╗FJEk]CT՟ YP:_|H1@ CBk]yKYp|og?*dGvzنzӴzjֺNkC~AbZƷ`.H)=!QͷVTT(| u78y֮}|[8-Vjp%2JPk[}ԉaH8Wpqhwr:vWª<}l77_~{s۴V+RCģ%WRZ\AqHifɤL36: #F:p]Bq/z{0CU6ݳEv_^k7'>sq*+kH%a`0ԣisqにtү04gVgW΂iJiS'3w.w}l6MC2uԯ|>JF5`fV5m`Y**Db1FKNttu]4ccsQNnex/87+}xaUW9y>ͯ骵G{䩓Գ3+vU}~jJ.NFRD7<aJDB1#ҳgSb,+CS?/ VG J?|?,2#M9}B)MiE+G`-wo߫V`fio(}S^4e~V4bHOYb"b#E)dda:'?}׮4繏`{7Z"uny-?ǹ;0MKx{:_pÚmFמ:F " .LFQLG)Q8qN q¯¯3wOvxDb\. BKD9_NN &L:4D{mm o^tֽ:q!ƥ}K+<"m78N< ywsard5+вz~mnG)=}lYݧNj'QJS{S :UYS-952?&O-:W}(!6Mk4+>A>j+i|<<|;ر^߉=HE|V#F)Emm#}/"y GII웻Jі94+v뾧xu~5C95~ūH>c@덉pʃ1/4-A2G%7>m;–Y,cyyaln" ?ƻ!ʪ<{~h~i y.zZB̃/,雋SiC/JFMmBH&&FAbϓO^tubbb_hZ{_QZ-sύodFgO(6]TJA˯#`۶ɟ( %$&+V'~hiYy>922 Wp74Zkq+Ovn錄c>8~GqܲcWꂎz@"1A.}T)uiW4="jJ2W7mU/N0gcqܗOO}?9/wìXžΏ0 >֩(V^Rh32!Hj5`;O28؇2#ݕf3 ?sJd8NJ@7O0 b־?lldщ̡&|9C.8RTWwxWy46ah嘦mh٤&l zCy!PY?: CJyв]dm4ǜҐR޻RլhX{FƯanшQI@x' ao(kUUuxW_Ñ줮[w8 FRJ(8˼)_mQ _!RJhm=!cVmm ?sFOnll6Qk}alY}; "baӌ~M0w,Ggw2W:G/k2%R,_=u`WU R.9T"v,<\Ik޽/2110Ӿxc0gyC&Ny޽JҢrV6N ``یeA16"J³+Rj*;BϜkZPJaÍ<Jyw:NP8/D$ 011z֊Ⱳ3ι֘k1V_"h!JPIΣ'ɜ* aEAd:ݺ>y<}Lp&PlRfTb1]o .2EW\ͮ]38؋rTJsǏP@芎sF\> P^+dYJLbJ C-xϐn> ι$nj,;Ǖa FU *择|h ~izť3ᤓ`K'-f tL7JK+vf2)V'-sFuB4i+m+@My=O҈0"|Yxoj,3]:cо3 $#uŘ%Y"y죯LebqtҢVzq¼X)~>4L׶m~[1_k?kxֺQ`\ |ٛY4Ѯr!)N9{56(iNq}O()Em]=F&u?$HypWUeB\k]JɩSع9 Zqg4ZĊo oMcjZBU]B\TUd34ݝ~:7ڶSUsB0Z3srx 7`:5xcx !qZA!;%͚7&P H<WL!džOb5kF)xor^aujƍ7 Ǡ8/p^(L>ὴ-B,{ۇWzֺ^k]3\EE@7>lYBȝR.oHnXO/}sB|.i@ɥDB4tcm,@ӣgdtJ!lH$_vN166L__'Z)y&kH;:,Y7=J 9cG) V\hjiE;gya~%ks_nC~Er er)muuMg2;֫R)Md) ,¶ 2-wr#F7<-BBn~_(o=KO㭇[Xv eN_SMgSҐ BS헃D%g_N:/pe -wkG*9yYSZS.9cREL !k}<4_Xs#FmҶ:7R$i,fi!~' # !6/S6y@kZkZcX)%5V4P]VGYq%H1!;e1MV<!ϐHO021Dp= HMs~~a)ަu7G^];git!Frl]H/L$=AeUvZE4P\.,xi {-~p?2b#amXAHq)MWǾI_r`S Hz&|{ +ʖ_= (YS(_g0a03M`I&'9vl?MM+m~}*xT۲(fY*V4x@29s{DaY"toGNTO+xCAO~4Ϳ;p`Ѫ:>Ҵ7K 3}+0 387x\)a"/E>qpWB=1 ¨"MP(\xp߫́A3+J] n[ʼnӼaTbZUWb={~2ooKױӰp(CS\S筐R*JغV&&"FA}J>G֐p1ٸbk7 ŘH$JoN <8s^yk_[;gy-;߉DV{c B yce% aJhDȶ 2IdйIB/^n0tNtџdcKj4϶v~- CBcgqx9= PJ) dMsjpYB] GD4RDWX +h{y`,3ꊕ$`zj*N^TP4L:Iz9~6s) Ga:?y*J~?OrMwP\](21sZUD ?ܟQ5Q%ggW6QdO+\@ ̪X'GxN @'4=ˋ+*VwN ne_|(/BDfj5(Dq<*tNt1х!MV.C0 32b#?n0pzj#!38}޴o1KovCJ`8ŗ_"]] rDUy޲@ Ȗ-;xџ'^Y`zEd?0„ DAL18IS]VGq\4o !swV7ˣι%4FѮ~}6)OgS[~Q vcYbL!wG3 7띸*E Pql8=jT\꘿I(z<[6OrR8ºC~ډ]=rNl[g|v TMTղb-o}OrP^Q]<98S¤!k)G(Vkwyqyr޽Nv`N/e p/~NAOk \I:G6]4+K;j$R:Mi #*[AȚT,ʰ,;N{HZTGMoּy) ]%dHء9Պ䠬|<45,\=[bƟ8QXeB3- &dҩ^{>/86bXmZ]]yޚN[(WAHL$YAgDKp=5GHjU&99v簪C0vygln*P)9^͞}lMuiH!̍#DoRBn9l@ xA/_v=ȺT{7Yt2N"4!YN`ae >Q<XMydEB`VU}u]嫇.%e^ánE87Mu\t`cP=AD/G)sI"@MP;)]%fH9'FNsj1pVhY&9=0pfuJ&gޤx+k:!r˭wkl03׼Ku C &ѓYt{.O.zҏ z}/tf_wEp2gvX)GN#I ݭ߽v/ .& и(ZF{e"=V!{zW`, ]+LGz"(UJp|j( #V4, 8B 0 9OkRrlɱl94)'VH9=9W|>PS['G(*I1==C<5"Pg+x'K5EMd؞Af8lG ?D FtoB[je?{k3zQ vZ;%Ɠ,]E>KZ+T/ EJxOZ1i #T<@ I}q9/t'zi(EMqw`mYkU6;[t4DPeckeM;H}_g pMww}k6#H㶏+b8雡Sxp)&C $@'b,fPߑt$RbJ'vznuS ~8='72_`{q纶|Q)Xk}cPz9p7O:'|G~8wx(a 0QCko|0ASD>Ip=4Q, d|F8RcU"/KM opKle M3#i0c%<7׿p&pZq[TR"BpqauIp$ 8~Ĩ!8Սx\ւdT>>Z40ks7 z2IQ}ItԀ<-%S⍤};zIb$I 5K}Q͙D8UguWE$Jh )cu4N tZl+[]M4k8֦Zeq֮M7uIqG 1==tLtR,ƜSrHYt&QP윯Lg' I,3@P'}'R˪e/%-Auv·ñ\> vDJzlӾNv5:|K/Jb6KI9)Zh*ZAi`?S {aiVDԲuy5W7pWeQJk֤#5&V<̺@/GH?^τZL|IJNvI:'P=Ϛt"¨=cud S Q.Ki0 !cJy;LJR;G{BJy޺[^8fK6)=yʊ+(k|&xQ2`L?Ȓ2@Mf 0C`6-%pKpm')c$׻K5[J*U[/#hH!6acB JA _|uMvDyk y)6OPYjœ50VT K}cǻP[ $:]4MEA.y)|B)cf-A?(e|lɉ#P9V)[9t.EiQPDѠ3ϴ;E:+Օ t ȥ~|_N2,ZJLt4! %ա]u {+=p.GhNcŞQI?Nd'yeh n7zi1DB)1S | S#ًZs2|Ɛy$F SxeX{7Vl.Src3E℃Q>b6G ўYCmtկ~=K0f(=LrAS GN'ɹ9<\!a`)֕y[uՍ[09` 9 +57ts6}b4{oqd+J5fa/,97J#6yν99mRWxJyѡyu_TJc`~W>l^q#Ts#2"nD1%fS)FU w{ܯ R{ ˎ󅃏џDsZSQS;LV;7 Od1&1n$ N /.q3~eNɪ]E#oM~}v֯FڦwyZ=<<>Xo稯lfMFV6p02|*=tV!c~]fa5Y^Q_WN|Vs 0ҘދU97OI'N2'8N֭fgg-}V%y]U4 峧p*91#9U kCac_AFңĪy뚇Y_AiuYyTTYЗ-(!JFLt›17uTozc. S;7A&&<ԋ5y;Ro+:' *eYJkWR[@F %SHWP 72k4 qLd'J "zB6{AC0ƁA6U.'F3:Ȅ(9ΜL;D]m8ڥ9}dU "v!;*13Rg^fJyShyy5auA?ɩGHRjo^]׽S)Fm\toy 4WQS@mE#%5ʈfFYDX ~D5Ϡ9tE9So_aU4?Ѽm%&c{n>.KW1Tlb}:j uGi(JgcYj0qn+>) %\!4{LaJso d||u//P_y7iRJ߬nHOy) l+@$($VFIQ9%EeKʈU. ia&FY̒mZ=)+qqoQn >L!qCiDB;Y<%} OgBxB!ØuG)WG9y(Ą{_yesuZmZZey'Wg#C~1Cev@0D $a@˲(.._GimA:uyw֬%;@!JkQVM_Ow:P.s\)ot- ˹"`B,e CRtaEUP<0'}r3[>?G8xU~Nqu;Wm8\RIkբ^5@k+5(By'L&'gBJ3ݶ!/㮻w҅ yqPWUg<e"Qy*167΃sJ\oz]T*UQ<\FԎ`HaNmڜ6DysCask8wP8y9``GJ9lF\G g's Nn͵MLN֪u$| /|7=]O)6s !ĴAKh]q_ap $HH'\1jB^s\|- W1:=6lJBqjY^LsPk""`]w)󭃈,(HC ?䔨Y$Sʣ{4Z+0NvQkhol6C.婧/u]FwiVjZka&%6\F*Ny#8O,22+|Db~d ~Çwc N:FuuCe&oZ(l;@ee-+Wn`44AMK➝2BRՈt7g*1gph9N) *"TF*R(#'88pm=}X]u[i7bEc|\~EMn}P瘊J)K.0i1M6=7'_\kaZ(Th{K*GJyytw"IO-PWJk)..axӝ47"89Cc7ĐBiZx 7m!fy|ϿF9CbȩV 9V-՛^pV̌ɄS#Bv4-@]Vxt-Z, &ֺ*diؠ2^VXbs֔Ìl.jQ]Y[47gj=幽ex)A0ip׳ W2[ᎇhuE^~q흙L} #-b۸oFJ_QP3r6jr+"nfzRJTUqoaۍ /$d8Mx'ݓ= OՃ| )$2mcM*cЙj}f };n YG w0Ia!1Q.oYfr]DyISaP}"dIӗթO67jqR ҊƐƈaɤGG|h;t]䗖oSv|iZqX)oalv;۩meEJ\!8=$4QU4Xo&VEĊ YS^E#d,yX_> ۘ-e\ "Wa6uLĜZi`aD9.% w~mB(02G[6y.773a7 /=o7D)$Z 66 $bY^\CuP. (x'"J60׿Y:Oi;F{w佩b+\Yi`TDWa~|VH)8q/=9!g߆2Y)?ND)%?Ǐ`k/sn:;O299yB=a[Ng 3˲N}vLNy;*?x?~L&=xyӴ~}q{qE*IQ^^ͧvü{Huu=R|>JyUlZV, B~/YF!Y\u_ݼF{_C)LD]m {H 0ihhadd nUkf3oٺCvE\)QJi+֥@tDJkB$1!Đr0XQ|q?d2) Ӣ_}qv-< FŊ߫%roppVBwü~JidY4:}L6M7f٬F "?71<2#?Jyy4뷢<_a7_=Q E=S1И/9{+93֮E{ǂw{))?maÆm(uLE#lïZ  ~d];+]h j?!|$F}*"4(v'8s<ŏUkm7^7no1w2ؗ}TrͿEk>p'8OB7d7R(A 9.*Mi^ͳ; eeUwS+C)uO@ =Sy]` }l8^ZzRXj[^iUɺ$tj))<sbDJfg=Pk_{xaKo1:-uyG0M ԃ\0Lvuy'ȱc2Ji AdyVgVh!{]/&}}ċJ#%d !+87<;qN޼Nفl|1N:8ya  8}k¾+-$4FiZYÔXk*I&'@iI99)HSh4+2G:tGhS^繿 Kتm0 вDk}֚+QT4;sC}rՅE,8CX-e~>G&'9xpW,%Fh,Ry56Y–hW-(v_,? ; qrBk4-V7HQ;ˇ^Gv1JVV%,ik;D_W!))+BoS4QsTM;gt+ndS-~:11Sgv!0qRVh!"Ȋ(̦Yl.]PQWgٳE'`%W1{ndΗBk|Ž7ʒR~,lnoa&:ü$ 3<a[CBݮwt"o\ePJ=Hz"_c^Z.#ˆ*x z̝grY]tdkP*:97YľXyBkD4N.C_[;F9`8& !AMO c `@BA& Ost\-\NX+Xp < !bj3C&QL+*&kAQ=04}cC!9~820G'PC9xa!w&bo_1 Sw"ܱ V )Yl3+ס2KoXOx]"`^WOy :3GO0g;%Yv㐫(R/r (s } u B &FeYZh0y> =2<Ϟc/ -u= c&׭,.0"g"7 6T!vl#sc>{u/Oh Bᾈ)۴74]x7 gMӒ"d]U)}" v4co[ ɡs 5Gg=XR14?5A}D "b{0$L .\4y{_fe:kVS\\O]c^W52LSBDM! C3Dhr̦RtArx4&agaN3Cf<Ԉp4~ B'"1@.b_/xQ} _߃҉/gٓ2Qkqp0շpZ2fԫYz< 4L.Cyυι1t@鎫Fe sYfsF}^ V}N<_`p)alٶ "(XEAVZ<)2},:Ir*#m_YӼ R%a||EƼIJ,,+f"96r/}0jE/)s)cjW#w'Sʯ5<66lj$a~3Kʛy 2:cZ:Yh))+a߭K::N,Q F'qB]={.]h85C9cr=}*rk?vwV렵ٸW Rs%}rNAkDv|uFLBkWY YkX מ|)1!$#3%y?pF<@<Rr0}: }\J [5FRxY<9"SQdE(Q*Qʻ)q1E0B_O24[U'],lOb ]~WjHޏTQ5Syu wq)xnw8~)c 쫬gٲߠ H% k5dƝk> kEj,0% b"vi2Wس_CuK)K{n|>t{P1򨾜j>'kEkƗBg*H%'_aY6Bn!TL&ɌOb{c`'d^{t\i^[uɐ[}q0lM˕G:‚4kb祔c^:?bpg… +37stH:0}en6x˟%/<]BL&* 5&fK9Mq)/iyqtA%kUe[ڛKN]Ě^,"`/ s[EQQm?|XJ߅92m]G.E΃ח U*Cn.j_)Tѧj̿30ڇ!A0=͜ar I3$C^-9#|pk!)?7.x9 @OO;WƝZBFU keZ75F6Tc6"ZȚs2y/1 ʵ:u4xa`C>6Rb/Yм)^=+~uRd`/|_8xbB0?Ft||Z\##|K 0>>zxv8۴吅q 8ĥ)"6>~\8:qM}#͚'ĉ#p\׶ l#bA?)|g g9|8jP(cr,BwV (WliVxxᡁ@0Okn;ɥh$_ckCgriv}>=wGzβ KkBɛ[˪ !J)h&k2%07δt}!d<9;I&0wV/ v 0<H}L&8ob%Hi|޶o&h1L|u֦y~󛱢8fٲUsւ)0oiFx2}X[zVYr_;N(w]_4B@OanC?gĦx>мgx>ΛToZoOMp>40>V Oy V9iq!4 LN,ˢu{jsz]|"R޻&'ƚ{53ўFu(<٪9:΋]B;)B>1::8;~)Yt|0(pw2N%&X,URBK)3\zz&}ax4;ǟ(tLNg{N|Ǽ\G#C9g$^\}p?556]/RP.90 k,U8/u776s ʪ_01چ|\N 0VV*3H鴃J7iI!wG_^ypl}r*jɤSR 5QN@ iZ#1ٰy;_\3\BQQ x:WJv츟ٯ$"@6 S#qe딇(/P( Dy~TOϻ<4:-+F`0||;Xl-"uw$Цi󼕝mKʩorz"mϺ$F:~E'ҐvD\y?Rr8_He@ e~O,T.(ފR*cY^m|cVR[8 JҡSm!ΆԨb)RHG{?MpqrmN>߶Y)\p,d#xۆWY*,l6]v0h15M˙MS8+EdI='LBJIH7_9{Caз*Lq,dt >+~ّeʏ?xԕ4bBAŚjﵫ!'\Ը$WNvKO}ӽmSşذqsOy?\[,d@'73'j%kOe`1.g2"e =YIzS2|zŐƄa\U,dP;jhhhaxǶ?КZ՚.q SE+XrbOu%\GتX(H,N^~]JyEZQKceTQ]VGYqnah;y$cQahT&QPZ*iZ8UQQM.qo/T\7X"u?Mttl2Xq(IoW{R^ ux*SYJ! 4S.Jy~ BROS[V|žKNɛP(L6V^|cR7i7nZW1Fd@ Ara{詑|(T*dN]Ko?s=@ |_EvF]׍kR)eBJc" MUUbY6`~V޴dJKß&~'d3i WWWWWW
Current Directory: /usr/share/guile/2.0/ice-9
Viewing File: /usr/share/guile/2.0/ice-9/getopt-long.scm
;;; Copyright (C) 1998, 2001, 2006, 2009, 2011 Free Software Foundation, Inc. ;;; ;;;; This library is free software; you can redistribute it and/or ;;;; modify it under the terms of the GNU Lesser General Public ;;;; License as published by the Free Software Foundation; either ;;;; version 3 of the License, or (at your option) any later version. ;;;; ;;;; This library is distributed in the hope that it will be useful, ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;;; Lesser General Public License for more details. ;;;; ;;;; You should have received a copy of the GNU Lesser General Public ;;;; License along with this library; if not, write to the Free Software ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ;;; Author: Russ McManus (rewritten by Thien-Thi Nguyen) ;;; Commentary: ;;; This module implements some complex command line option parsing, in ;;; the spirit of the GNU C library function `getopt_long'. Both long ;;; and short options are supported. ;;; ;;; The theory is that people should be able to constrain the set of ;;; options they want to process using a grammar, rather than some arbitrary ;;; structure. The grammar makes the option descriptions easy to read. ;;; ;;; `getopt-long' is a procedure for parsing command-line arguments in a ;;; manner consistent with other GNU programs. `option-ref' is a procedure ;;; that facilitates processing of the `getopt-long' return value. ;;; (getopt-long ARGS GRAMMAR) ;;; Parse the arguments ARGS according to the argument list grammar GRAMMAR. ;;; ;;; ARGS should be a list of strings. Its first element should be the ;;; name of the program; subsequent elements should be the arguments ;;; that were passed to the program on the command line. The ;;; `program-arguments' procedure returns a list of this form. ;;; ;;; GRAMMAR is a list of the form: ;;; ((OPTION (PROPERTY VALUE) ...) ...) ;;; ;;; Each OPTION should be a symbol. `getopt-long' will accept a ;;; command-line option named `--OPTION'. ;;; Each option can have the following (PROPERTY VALUE) pairs: ;;; ;;; (single-char CHAR) --- Accept `-CHAR' as a single-character ;;; equivalent to `--OPTION'. This is how to specify traditional ;;; Unix-style flags. ;;; (required? BOOL) --- If BOOL is true, the option is required. ;;; getopt-long will raise an error if it is not found in ARGS. ;;; (value BOOL) --- If BOOL is #t, the option accepts a value; if ;;; it is #f, it does not; and if it is the symbol ;;; `optional', the option may appear in ARGS with or ;;; without a value. ;;; (predicate FUNC) --- If the option accepts a value (i.e. you ;;; specified `(value #t)' for this option), then getopt ;;; will apply FUNC to the value, and throw an exception ;;; if it returns #f. FUNC should be a procedure which ;;; accepts a string and returns a boolean value; you may ;;; need to use quasiquotes to get it into GRAMMAR. ;;; ;;; The (PROPERTY VALUE) pairs may occur in any order, but each ;;; property may occur only once. By default, options do not have ;;; single-character equivalents, are not required, and do not take ;;; values. ;;; ;;; In ARGS, single-character options may be combined, in the usual ;;; Unix fashion: ("-x" "-y") is equivalent to ("-xy"). If an option ;;; accepts values, then it must be the last option in the ;;; combination; the value is the next argument. So, for example, using ;;; the following grammar: ;;; ((apples (single-char #\a)) ;;; (blimps (single-char #\b) (value #t)) ;;; (catalexis (single-char #\c) (value #t))) ;;; the following argument lists would be acceptable: ;;; ("-a" "-b" "bang" "-c" "couth") ("bang" and "couth" are the values ;;; for "blimps" and "catalexis") ;;; ("-ab" "bang" "-c" "couth") (same) ;;; ("-ac" "couth" "-b" "bang") (same) ;;; ("-abc" "couth" "bang") (an error, since `-b' is not the ;;; last option in its combination) ;;; ;;; If an option's value is optional, then `getopt-long' decides ;;; whether it has a value by looking at what follows it in ARGS. If ;;; the next element is does not appear to be an option itself, then ;;; that element is the option's value. ;;; ;;; The value of a long option can appear as the next element in ARGS, ;;; or it can follow the option name, separated by an `=' character. ;;; Thus, using the same grammar as above, the following argument lists ;;; are equivalent: ;;; ("--apples" "Braeburn" "--blimps" "Goodyear") ;;; ("--apples=Braeburn" "--blimps" "Goodyear") ;;; ("--blimps" "Goodyear" "--apples=Braeburn") ;;; ;;; If the option "--" appears in ARGS, argument parsing stops there; ;;; subsequent arguments are returned as ordinary arguments, even if ;;; they resemble options. So, in the argument list: ;;; ("--apples" "Granny Smith" "--" "--blimp" "Goodyear") ;;; `getopt-long' will recognize the `apples' option as having the ;;; value "Granny Smith", but it will not recognize the `blimp' ;;; option; it will return the strings "--blimp" and "Goodyear" as ;;; ordinary argument strings. ;;; ;;; The `getopt-long' function returns the parsed argument list as an ;;; assocation list, mapping option names --- the symbols from GRAMMAR ;;; --- onto their values, or #t if the option does not accept a value. ;;; Unused options do not appear in the alist. ;;; ;;; All arguments that are not the value of any option are returned ;;; as a list, associated with the empty list. ;;; ;;; `getopt-long' throws an exception if: ;;; - it finds an unrecognized property in GRAMMAR ;;; - the value of the `single-char' property is not a character ;;; - it finds an unrecognized option in ARGS ;;; - a required option is omitted ;;; - an option that requires an argument doesn't get one ;;; - an option that doesn't accept an argument does get one (this can ;;; only happen using the long option `--opt=value' syntax) ;;; - an option predicate fails ;;; ;;; So, for example: ;;; ;;; (define grammar ;;; `((lockfile-dir (required? #t) ;;; (value #t) ;;; (single-char #\k) ;;; (predicate ,file-is-directory?)) ;;; (verbose (required? #f) ;;; (single-char #\v) ;;; (value #f)) ;;; (x-includes (single-char #\x)) ;;; (rnet-server (single-char #\y) ;;; (predicate ,string?)))) ;;; ;;; (getopt-long '("my-prog" "-vk" "/tmp" "foo1" "--x-includes=/usr/include" ;;; "--rnet-server=lamprod" "--" "-fred" "foo2" "foo3") ;;; grammar) ;;; => ((() "foo1" "-fred" "foo2" "foo3") ;;; (rnet-server . "lamprod") ;;; (x-includes . "/usr/include") ;;; (lockfile-dir . "/tmp") ;;; (verbose . #t)) ;;; (option-ref OPTIONS KEY DEFAULT) ;;; Return value in alist OPTIONS using KEY, a symbol; or DEFAULT if not ;;; found. The value is either a string or `#t'. ;;; ;;; For example, using the `getopt-long' return value from above: ;;; ;;; (option-ref (getopt-long ...) 'x-includes 42) => "/usr/include" ;;; (option-ref (getopt-long ...) 'not-a-key! 31) => 31 ;;; Code: (define-module (ice-9 getopt-long) #:use-module ((ice-9 common-list) #:select (remove-if-not)) #:use-module (srfi srfi-9) #:use-module (ice-9 match) #:use-module (ice-9 regex) #:use-module (ice-9 optargs) #:export (getopt-long option-ref)) (define %program-name (make-fluid "guile")) (define (program-name) (fluid-ref %program-name)) (define (fatal-error fmt . args) (format (current-error-port) "~a: " (program-name)) (apply format (current-error-port) fmt args) (newline (current-error-port)) (exit 1)) (define-record-type option-spec (%make-option-spec name required? option-spec->single-char predicate value-policy) option-spec? (name option-spec->name set-option-spec-name!) (required? option-spec->required? set-option-spec-required?!) (option-spec->single-char option-spec->single-char set-option-spec-single-char!) (predicate option-spec->predicate set-option-spec-predicate!) (value-policy option-spec->value-policy set-option-spec-value-policy!)) (define (make-option-spec name) (%make-option-spec name #f #f #f #f)) (define (parse-option-spec desc) (let ((spec (make-option-spec (symbol->string (car desc))))) (for-each (match-lambda (('required? val) (set-option-spec-required?! spec val)) (('value val) (set-option-spec-value-policy! spec val)) (('single-char val) (or (char? val) (error "`single-char' value must be a char!")) (set-option-spec-single-char! spec val)) (('predicate pred) (set-option-spec-predicate! spec (lambda (name val) (or (not val) (pred val) (fatal-error "option predicate failed: --~a" name))))) ((prop val) (error "invalid getopt-long option property:" prop))) (cdr desc)) spec)) (define (split-arg-list argument-list) ;; Scan ARGUMENT-LIST for "--" and return (BEFORE-LS . AFTER-LS). ;; Discard the "--". If no "--" is found, AFTER-LS is empty. (let loop ((yes '()) (no argument-list)) (cond ((null? no) (cons (reverse yes) no)) ((string=? "--" (car no)) (cons (reverse yes) (cdr no))) (else (loop (cons (car no) yes) (cdr no)))))) (define short-opt-rx (make-regexp "^-([a-zA-Z]+)(.*)")) (define long-opt-no-value-rx (make-regexp "^--([^=]+)$")) (define long-opt-with-value-rx (make-regexp "^--([^=]+)=(.*)")) (define (looks-like-an-option string) (or (regexp-exec short-opt-rx string) (regexp-exec long-opt-with-value-rx string) (regexp-exec long-opt-no-value-rx string))) (define (process-options specs argument-ls stop-at-first-non-option) ;; Use SPECS to scan ARGUMENT-LS; return (FOUND . ETC). ;; FOUND is an unordered list of option specs for found options, while ETC ;; is an order-maintained list of elements in ARGUMENT-LS that are neither ;; options nor their values. (let ((idx (map (lambda (spec) (cons (option-spec->name spec) spec)) specs)) (sc-idx (map (lambda (spec) (cons (make-string 1 (option-spec->single-char spec)) spec)) (remove-if-not option-spec->single-char specs)))) (let loop ((unclumped 0) (argument-ls argument-ls) (found '()) (etc '())) (define (eat! spec ls) (cond ((eq? 'optional (option-spec->value-policy spec)) (if (or (null? ls) (looks-like-an-option (car ls))) (loop (- unclumped 1) ls (acons spec #t found) etc) (loop (- unclumped 2) (cdr ls) (acons spec (car ls) found) etc))) ((eq? #t (option-spec->value-policy spec)) (if (or (null? ls) (looks-like-an-option (car ls))) (fatal-error "option must be specified with argument: --~a" (option-spec->name spec)) (loop (- unclumped 2) (cdr ls) (acons spec (car ls) found) etc))) (else (loop (- unclumped 1) ls (acons spec #t found) etc)))) (match argument-ls (() (cons found (reverse etc))) ((opt . rest) (cond ((regexp-exec short-opt-rx opt) => (lambda (match) (if (> unclumped 0) ;; Next option is known not to be clumped. (let* ((c (match:substring match 1)) (spec (or (assoc-ref sc-idx c) (fatal-error "no such option: -~a" c)))) (eat! spec rest)) ;; Expand a clumped group of short options. (let* ((extra (match:substring match 2)) (unclumped-opts (append (map (lambda (c) (string-append "-" (make-string 1 c))) (string->list (match:substring match 1))) (if (string=? "" extra) '() (list extra))))) (loop (length unclumped-opts) (append unclumped-opts rest) found etc))))) ((regexp-exec long-opt-no-value-rx opt) => (lambda (match) (let* ((opt (match:substring match 1)) (spec (or (assoc-ref idx opt) (fatal-error "no such option: --~a" opt)))) (eat! spec rest)))) ((regexp-exec long-opt-with-value-rx opt) => (lambda (match) (let* ((opt (match:substring match 1)) (spec (or (assoc-ref idx opt) (fatal-error "no such option: --~a" opt)))) (if (option-spec->value-policy spec) (eat! spec (cons (match:substring match 2) rest)) (fatal-error "option does not support argument: --~a" opt))))) ((and stop-at-first-non-option (<= unclumped 0)) (cons found (append (reverse etc) argument-ls))) (else (loop (- unclumped 1) rest found (cons opt etc))))))))) (define* (getopt-long program-arguments option-desc-list #:key stop-at-first-non-option) "Process options, handling both long and short options, similar to the glibc function 'getopt_long'. PROGRAM-ARGUMENTS should be a value similar to what (program-arguments) returns. OPTION-DESC-LIST is a list of option descriptions. Each option description must satisfy the following grammar: <option-spec> :: (<name> . <attribute-ls>) <attribute-ls> :: (<attribute> . <attribute-ls>) | () <attribute> :: <required-attribute> | <arg-required-attribute> | <single-char-attribute> | <predicate-attribute> | <value-attribute> <required-attribute> :: (required? <boolean>) <single-char-attribute> :: (single-char <char>) <value-attribute> :: (value #t) (value #f) (value optional) <predicate-attribute> :: (predicate <1-ary-function>) The procedure returns an alist of option names and values. Each option name is a symbol. The option value will be '#t' if no value was specified. There is a special item in the returned alist with a key of the empty list, (): the list of arguments that are not options or option values. By default, options are not required, and option values are not required. By default, single character equivalents are not supported; if you want to allow the user to use single character options, you need to add a `single-char' clause to the option description." (with-fluids ((%program-name (car program-arguments))) (let* ((specifications (map parse-option-spec option-desc-list)) (pair (split-arg-list (cdr program-arguments))) (split-ls (car pair)) (non-split-ls (cdr pair)) (found/etc (process-options specifications split-ls stop-at-first-non-option)) (found (car found/etc)) (rest-ls (append (cdr found/etc) non-split-ls))) (for-each (lambda (spec) (let ((name (option-spec->name spec)) (val (assq-ref found spec))) (and (option-spec->required? spec) (or val (fatal-error "option must be specified: --~a" name))) (let ((pred (option-spec->predicate spec))) (and pred (pred name val))))) specifications) (for-each (lambda (spec+val) (set-car! spec+val (string->symbol (option-spec->name (car spec+val))))) found) (cons (cons '() rest-ls) found)))) (define (option-ref options key default) "Return value in alist OPTIONS using KEY, a symbol; or DEFAULT if not found. The value is either a string or `#t'." (or (assq-ref options key) default)) ;;; getopt-long.scm ends here