ÿØÿà JFIF    ÿÛ „ !.%+&8&+/1555$;@;4?.451 4,$,44444444444414444444444444444444444444444444444444ÿÀ  á á" ÿÄ     ÿÄ ?    !1AQaq"2‘¡±ÁðBRbrÑá#‚’¢²3S CñÿÄ   ÿÄ !    !1QAa‘2ÿÚ   ? 5˜Z¯V¦cø)›t/? z¨±>Õ5€¶‹Á¤·¼z¼Ü¬+ñ®v¤¨_ˆR­BFn©—˜ý®ç̝P8gýt·ÉSTŦˆìät?þé¼íìN/Þa)ì–í6ô… Ï¿øÃj´¿KÇü]ÿ ªô¹-eKànëÕHTx}ýSÜ›ÿ ”7Ø×&µ<¦  ¥ÑO¶[Ù¯ä¨ÞÃÿ PZ-¬;#õ|•oaÿ ©CìÞz3˜öː/¤­ñTûIØ}š^ mÓ%ªxˆ¥ÉŸu=Z+ISe¿45™¼u;ú&WØ÷€æßQ™®{|íx*TC“#ZŠìZ§²‹ 6pv…³¿¡äª*áZÐ%ÒOáˆo"x«OHk w±æ+¬V(kMúŸ5Vö«$ ÁrÏbàb57/luR ¸ÑÛj Òµì`Мq­û žICÀÊ•©4€Âcà¨Ï€O´<èÐ:›ù(Ë^L8þ‘ÍÌ#¸Ð_Ì©ÙK(Öz 4¬û+¸;ü’V’84‘¬ÃŽ:[â‡ÔÌáõp¢~§ªlæ£ö{®G>J¼"°‡7¯ÆÉèßû ‹É‹§ÁòÃýâßî ^ƾÙõ‹×óH#«LP½ïX=xÑÍ$|W?•~• îëÔ©ª‹ {ÝT…Kÿ ”hûâá)J*ö˜–ÔU;iÇ€/ ÆþjóZ\ýwØ=Ìm ºèËL9 ýèÆð/¨’¥öo=nË.%Îì ŽÕ¯È|{Oj²ƒE6e/ßdÄõ²Ìâ1O®ò×TsəԸhOMýíMˆ¿¼H˜l²,7Â¥#MF/Úf°Ö½± ¸–dr‹NýÊ íjqx{œÉ ä-È ¦ øÄër¨q°ð †nцýÑÄÆ’mä…n<0È™;ÁÝá¯ÁZƒ7FÀmì­ É&9ˆîéi¶ùN§Y• ÃZãAâ?•‡©‰ , ó¾IŸŠc1 4â&y­&pŠ­6;M À 0¹qç»p.á …ŸÅáK@%6·y6ƒ‰3?”úºŽ‰éX5ªPT §µ!=Mž«Ú½‹ÅgÂSâÉaþÓoö–¯ÁÔìR>5éÿ üs¶ÆUcÌ kÇR ]ÿ ù¬¼«VŽ;Â|‡~¢¦”ÏŰæ {L™Õ°Óv¹ò¸írޡעCÃ!íVÕ {¶»sŒNPg/ "uÕbkm²“$ďå¿é¹§°½æz¯6 †s¿!s–wÚÝ“™Œ °.ûj>·+™Òa…©Œ&rÝÎtÛë긪Ît’LAVp%c Úý[ÄzJ¾ÇàXXç@˜ó<êL]·T˜¾¥1Ó©V‡g´æ½¦Ý@¹óø!_@´ÞâSÁ —S3™•& ]@JHÚý©ZŽ €×æÔr»Áf!‡yÞ4Mv*èÓã_{‘åóUuљØ«Oïé*®EvÑ Œ÷‡U \"㪒ÍK+À 4“M¡ï:0¥5í!'<@î´”>Ç»&Z–ïCCV˜Ì5Šo&îhè.žû |ÓK©h$s6KìŒëã)¹hI¦GïOåóI;ììü#É$Š0…Ææ¥TØ.5­¾gn´ “ÂÖ\:hœ89G)J@„}œ:’Ò{/Š"¦_Æ×7Æ3VÇŠÊa]ÚŒÙ€Ä–=®uÁßâACZƒ§§£ Qnâ:«,×{tyø¬iÛcœÜÄ€H½ÄÍCk´÷šß .W'b¤Íåh]÷€=,Žv×cÚEÚHXJX¶îo¨FÒtèöŸ>ªª6[J®Fµ£sGÁeqõfe\íjÒÐïÄÐGˆe1Ø‹.Ø”‘Ëuø Y­ˆÜ ŽG|zùªüMpDnQWÄ”%JŠ™)â*p@Örš«ÕT2Ð%ˆG#ª„ ·¤!°ŸOTÂT¸aÚ%4&h™LµšØüÐ.F¿²ÐÞ_Ç‚¾ÅÃaÜ÷09Æ q€öy˜v‡85õN÷]¬äѼóS{°_MެúÔ#°Ç¸0åÞè2ëôPcvÆw9®ií1Ä8F™˜à‰´+‰Ik1òÝ7“Ñ×ÒsÝ\x‚h`ÞÑ`ó"|µEcý£n˜h`}GÞ !±ù²Ápü²ß6 0ïi󜵩SÈÇ7˜-ÕURO˜¦´f$ªž-Í6(œ}<„ éc øs]ŽŽ„*—¾ ìdŽ„)méª\¿êÎIg¾ØÞ~I#C/¼¼´EÁÈŽi8“©õådô·>euä ƒ'Ê×लR1ÉJE1ÐAát`t;ÇР%Ý<‡¥„ÍÆ`×Oyó)õiI€ñQaŸ4Ûù\áàaÃÔ¹HÃu¹*k€¦<„e S‡&õÏ B!ŽhüÞ`yj}mªf×\¿ Ç~æ­9‡û\՞Ǖg²1Žû5V7 !àöšm° c`ܬøÇìµÒ'P"?…´Ö,"§^•õލsÔ)6˜sæéÍR¼ ò|Sl”‹7 nPW Gòú÷½§O¯‡„l¡kSÞŒr½PÊ@æ¢pŽ-mÿ #Ÿ˜Àº¶Áä¦;ïÔæ$1££`“Õ>„—·ž)ßð³ñ#Ï Ô$¶œ‰ÊE‹À;÷º ¯«P:Ñ”8–IÊtpÞ3ª“>ê“þës4ò2OÏÕ­±zô†Õ§‰.÷ä¸;¿˜“'œ›žª}«Œ{ª±Ì 9ÔóÞÕ‡0 $íWV3Üì¬ —@kÝ4@¿r¼±½¬™›?øØæ´'Áé®CË3-g$˜ö‡×auÚi´Žp/êÛ æF›Ú2v‹ã¿¿,nB1̨ƃqÞa5͝@&Æû“él÷ \C²½UÍc ¯k×¢U ÖéQå™—-r wô ÞÏ<Ò=&=ÿ Ôê Òêˈt,i—;LîÜ á¸*ÚÃ1$êL•LÍ <É)ýÐà’ ;F™{ƒ™˜€&'}‚ãÄK`¡ÞT@I;®žZóè‚s’7®°›+§O­Åq©é»²9<Ô J ¼9O’HL»Ùïì¸rk¼Ž_ý‘TŸu[²ßÚŒ·ü÷B%¯E ŸÔX5êO´ Ç•€’I0 ÉJX` ñ¹õ%;µŸD‘«´€àwÒ™U ûئžÖö\×®×´8 ½‡ºÐÆÓ§?Àkmœ=;d5*@-ì0F Rªýš[Ü6âö̃ڸr*KA9· u*µæ£?U¸Âêí†8@¦X4 e-ò„0s{ HâUpU?¼mñRa°®a%Ð'tÉ×’\¾ÊÉ]t›h>·(Ë@R¼¡Ãt h}’O÷au<+nT…Ö…MӐ??Óe95 q>í/;&JSû °¯ÊéÞ øƒ*Ã2½Ài&:nôUl=¾¿5eˆ3”ñc|Ú2V”>„»&eE;«ÚäC p¢Û úy 9š[ŒÌx¼擼A&DåÒ¯ˆ¤ÀÌ;"˜ ÏQä¸åhÊ}Ûq«Û0WžÒ|»€ø®öCm5•\ÇÀ§Pe3£]0ÃàLDÉ‰1øªxjgwT‚÷¿LΨK‹›ùs—xˆÜ±µ kæ¸f‰‰ÜGk/LÛØ6d9ò¶ùA{ƒA3š/¬D¬khÓk‰`˜"㯒r¿±Óã jx‡°e}<Ñø\3y:'À•/h½Í€Ç4~g ?Û(¼]v‘ªlKÎâ~?O‚W%{Ì:“'©úNq¾›úo(X’¥¯ˆ nFê{Ç€ü?º'ë ø‹ì Þ09ŒÌç9Æ —ËC`j@ÓÄ(+a‹un¸#ÂꟋ{K`‘ÑÍÍ'à´»/Û,KW;Þ4²þð ï Nm|~fGÏ(…³Ã)«1ö­Õ ¥‡¨©ƒÃ™ü-s=à=U66Ï«Ýc蓦W¹íž®›nÔ%êÇìŒ<#Ü×84ån®Ð ÒåOC` ñânÑs‡¢ç 1õ%Îhì½Ã½® e:ݼUZo™`  ÅZŸŒÊ«ê1ÏÄo$q¹Þ€©ˆhÐÉä¯ñ[!…Ú˜àJ:x2$Íß&PåT£6ç— ‡Í*4Ýšçjÿ ‰É nófÐ ó(L5C•åÆ\rMÒ@ò }y-W}™üýVù—ú¢=Ù”c®‘< M ž ´Phr ¦©TD ‘ù.$´÷O‡‘V2Æò.=IUŒ=ž‡â¬i™aþÓåÙ?òUø'ØÖ•.~* šTŒ!•-×áºTâ®ä#õü'´ eýlYÅÓeÕKÂrT"CÚ@u!Óxƒ{š3€}1¿(r}%«nËamjÑ%ÑNEò v ˜à  σöK³,*º.àzù¨™Ó ÚçâU¦*¿ 9{%Ö¹ njûdaXöb) kÛÆ±ûÓ\°M7ˆÂ=û›ç¿Ã‚­V»Cg–8ÙêE- j)k$º`Ã-ùEýeBÆÇ]c¡°ñty&Òd0nõ'¡W+ƒ*|–øµFa\GQªEAÔp5\Ǽ·¼Ç8·õ -â§Ú[ ‡ uZeÖ 3}×d'+¹:ð+K†Û®s!Ï$úe€<Û”x)1»a­¡LC]¸µík…ÚàA»AYº{†ªS[¦5HÒ7ù --,ísòDØ€èk ÞÀîÜ ò@â( ËNˆë›4ô½•/¦o‡€Û7 ê•ÆêòðÜy'Án½µ á˜ݦ ndeo…[ì¶Ê,¥R³Ä=À±—–ß;£™´ñSâ*g§”ïaið‘Jå~™ÓÞ ß³Õ¢»8x埒²52>AÊb&-÷\7´éÄù€T˜,w;3{ï˜k…à¹ÄqÀ«œ{€\ ˆ¾[´¨јr &Úé„Ívˆ±8†¿]|¬ņ4I×pÞS1ÈÖz‰#Ìv‡G!YNògñ:màTz¢Ý1ô©^O=~ë|5Bã™ç•¼µõ•bÆ@úÕS¬ÈŒ#¬zünrŸ û” Z²•èðV"ÁHÚý©wÝ €7¼Ìu1hÑa3Éä û f$o¿É ™Ú›ÝçnpÒ3äÌ3†Í§,Äï]$‰/pê †«À¼¸e9­Æê_C]žƒ·ý·frÁN«, E=›Çq -‰öŒ:aÏ¿±í&£Í:-} 84‘ÿ eƒQÑeëSsuiA ³g㟥ú£?ÿ ʼn*”“÷aühe:ÊWa@ÒÞk±eØ] F Ô—r.åä˜ @ö¥ªZoÐýYL·¥S²G/‡ñ <~*ZÆ´è>JlòàÛÆ½ÿ 窘ìGN¢:I®KšJp/`íIÁÀõ#Ä-€ö­šµŒoF4|ÆQØÆ@Ì|£Ô…¢À{9˜è½Üó›€ôYÒÎYsið;ís¤€à²ˆ‚4qÉVŒI$ ‰"° æµ8cXGjœˏ¡Aâý•ËÜ¢ûï e·çLx']á"oÅÎê3¯Ç—¹”ó0nå‚âg{Œñ> S´˜îè°g238‚ãköÝfÚd´6Ò€;ò÷±¢™¼›º ¢Æ'¥Ðx'e¬ç ]bÈÆV¢ó‹kýBO ðÊâ$Ÿ!×T 3Mýמ žìٍàÌü‘8÷€àæØ8æ©6‰©L´«…oãpð„~Çk‰!ñ;‹”ÛžÍ àž±z Ÿôû øŸÝužÏ;ÿ #|u6™Þ¬ÚˆÐõA4¶â|ôl|Ê2ŽÇ¤ÝÅÇY.<#Aí.k§hóF‚”Y; M½Ö4hŸ4&›­¿tès´%FìL¥£Ãk‰ÇT¤haÁ¤ÚxfÉ`ÑìË›>i 3t‚:,–+^÷´–{Û–Nxi"x‘Ûg î¨>¥Õ܁ùZH,2Û“:8xÊ¢Çí9.É-Ìâã-=çjwµS˜dütžçwýGòú®®ûº_ˆýx$–¡ãøO EÚÛÏ÷R„×w+3£Á£öUMyR²¹âŒ°š›¸Ñãò9§Ó_Dl+Ùßc›úšGÅÌc†Ž!Ko=¶.‘Îÿ c²(2®V mª.ÿ ¹B›¹å ù„öŸSV>™ü¯$y:G¢Z×àøúdî¹û­·ýÇ´:•c LÍõi_‹ö+ÎæGÊè>OŠ•äž´§Þ{X}¨1ÚTc›»Qþ•êô°t¿OP?eæ~É{5]•ÙR£r5†nZ\ã@ &îJõ ¾àC°þV>fé¥/ü5ñÊIº_é5 ;e­h<@ Ä&æÃëE%;X,ÒãÆÞ`Oò¦kŸm#˜!ÀyÄ¢| óLšò¥Ä` ¶R=|ÈCâh5ò3DˆïF†ðÒ#ÅìÛœ?¸yhBãœí ZxßÎÄhºRK„`Þödvײ™ÀÈÑÒgŒuY w³%†ƒÓzõ ÖÏp‚dH®¦A´ù§»ÓÇMæ~)ˆð‡û:ù&Ä •vGD´À n ݇¼Ö8Fö óáà£~Ë¥x`oK|Ä?fxiØü%pìR>éò+Û±éÎ>núlFŤ'tq8LZÏvÃ?„¡ß±È⽆¯³íü@x|PöUäèØã¡ð‚ŒAìÏ"vÍwóŸÍ{ ý0.z È•Ö{,N¡£¡ŸKÕÙž>Ýœþ ÍÀ°<×EA!Å‚D™IúOÍ¡>ôG}Â` ÍßkÜL™Ž Þð™ {IøF²¹òQ3&!ÃÂÞz.d&Ï-sH¸,Ôõ˜ŽP€ 77ˆÝ¼ÊëÜw =cÕ Ú,ØÐ5ÎYÐ)ì´öœgŒ[¤ßv㙑8心>h]§µháYš£²ºÑ.{Ï7Sð•?´~×SÃKýJÛ˜ ™Íäiúu<µX¶1õ^kâçIÑ£sZ4h>j*ÔšD:4­¿_ ÷¸ Õxæÿ ¸?Mù _•­ÊÐ ä ÷ý ÑwL œ­ïnTkÛUÍN©ë:¦fV ¶ÜÔÜMªÅâA½–¿R×TXš-%iTÊT•‡Ù‚JôϐZxWÑè‰f‰òG º ×Õû2aZ7OU3[“×AT–ÞŒ…-‘¤”Ì ì&(ˆ¿­•ƒkï’:ðY¦W‘ Å)“†‘˜³Åtcø˜ñTÂwÚÇ4|üLÇªí–v- qˆèU qPE.†â‘˜µ Æ,ÐÅs]8¾„oúÑ i>ÜxxÈó)ƒ ´æÁâØ$À‰vžŸf$Ž |ãw;ÀÁIJ»b` {¦Ó¤Ú$©YÀ‘n@Óïž«9J¼êG m¤ ܯ¹ÌW4€ÐÒÅÛ‡#褕Ÿn-?í|с¥÷Ú¹¬'´ÞÜ9ÓK `hê£SÄSà?7—Wí_´…óB›»:=Ãïq`<8ñÓŒÑlú2d¬ê³£hÖ[l|$vÝro~'R®‰§°ñmY ͧäP |PUª¹·:3Œ[Û{Xÿ ºâ@‚W–Äé u‚ ¯´*=íή.pûÒdt @G‰¬ s¸ ëÉücr ÞæÑ¨Ê@>¤¢Ö±. Þ'¯°ÌME[YéïĵÂCå½ Ué©Áû'Ê9%eÔðNU”ë‘ÌsD3/®+UI˜9h.WC”빓$#:pz:YÓ ¿xž* ³$Í +$kñAŠ‹†¢ Uê>¸)_š¬÷©ßAÂÔb9ÇU ¯¾á•9¯ÏÏ÷O÷¼¼Fähal1‰3Ì[Ïr•´UCksNÐ] R‘¸¥H+§Šé†c©vÖÞ0iÓ76s†î!§=ß ¼~Ô'°Ãmäoäš³ªøi1úÉ)³yV8 CLÄØÁ‘WYïi€H6ÖÑiámø^ÈY´°Ñ7¥Û*—Ñ©L«Qƒï—Ùrÿ ›£Ð*š¸ˆL©ˆ$ˆ ÷¾D§9È®«qbqC)–ˆïv´çñsÑVT­Ø, <àïºÀO«Jý·õ àfPìð .wFšir´þ’2_Y *Æ€x\« ì€9š@ Ž|F⇥ˆkZ@hÖÄ0t¿-<“‹qµ¾*ZL¤Ú)&BJpÓF5=$„at*Zš$’ÑtdûÝRI1 2މ$€$I$#‰SÞ’Hë¬ï;Á$¡t$’`<(ñÇt)$‡Ð.Êf¢X’Kt=Éé$‚ˆªè¢oÝëòI%Rgcª÷ŠyI%¡‰ÿ !ñ)´õ $¤ Ô’IIGÿÙ(* Module: Shellvars Generic lens for shell-script config files like the ones found in /etc/sysconfig About: License This file is licenced under the LGPL v2+, like the rest of Augeas. About: Lens Usage To be documented *) module Shellvars = autoload xfm (* Delete a blank line, rather than mapping it *) let del_empty = del (Util.empty_generic_re . "\n") "\n" let empty = Util.empty let empty_part_re = Util.empty_generic_re . /\n+/ let eol = del (/[ \t]+|[ \t]*[;\n]/ . empty_part_re*) "\n" let semicol_eol = del (/[ \t]*[;\n]/ . empty_part_re*) "\n" let brace_eol = del /[ \t\n]+/ "\n" let key_re = /[A-Za-z0-9_][-A-Za-z0-9_]*(\[[0-9A-Za-z_,]+\])?/ - ("unset" | "export") let matching_re = "${!" . key_re . /[\*@]\}/ let eq = Util.del_str "=" let eol_for_comment = del /([ \t]*\n)([ \t]*(#[ \t]*)?\n)*/ "\n" let comment = Util.comment_generic_seteol /[ \t]*#[ \t]*/ " # " eol_for_comment (* comment_eol in shell MUST begin with a space *) let comment_eol = Util.comment_generic_seteol /[ \t]+#[ \t]*/ " # " eol_for_comment let comment_or_eol = comment_eol | semicol_eol let xchgs = Build.xchgs let semicol = del /;?/ "" let char = /[^`;()'"&|\n\\# \t]#*|\\\\./ let dquot = let char = /[^"\\]|\\\\./ | Rx.cl in "\"" . char* . "\"" (* " Emacs, relax *) let squot = /'[^']*'/ let bquot = /`[^`\n]+`/ (* dbquot don't take spaces or semi-colons *) let dbquot = /``[^` \t\n;]+``/ let dollar_assign = /\$\([^\(\)#\n]*\)/ let dollar_arithm = /\$\(\([^\)#\n]*\)\)/ let anyquot = (char|dquot|squot|dollar_assign|dollar_arithm)+ | bquot | dbquot let sto_to_semicol = store (anyquot . (Rx.cl_or_space . anyquot)*) (* Array values of the form '(val1 val2 val3)'. We do not handle empty *) (* arrays here because of typechecking headaches. Instead, they are *) (* treated as a simple value *) let array = let array_value = store anyquot in del /\([ \t]*/ "(" . counter "values" . [ seq "values" . array_value ] . [ del /[ \t\n]+/ " " . seq "values" . array_value ] * . del /[ \t]*\)/ ")" (* Treat an empty list () as a value '()'; that's not quite correct *) (* but fairly close. *) let simple_value = let empty_array = /\([ \t]*\)/ in store (anyquot | empty_array)? let export = [ key "export" . Util.del_ws_spc ] let kv = Util.indent . export? . key key_re . eq . (simple_value | array) let var_action (name:string) = Util.indent . del name name . Util.del_ws_spc . label ("@" . name) . counter "var_action" . Build.opt_list [ seq "var_action" . store (key_re | matching_re) ] Util.del_ws_spc let unset = var_action "unset" let bare_export = var_action "export" let source = Util.indent . del /\.|source/ "." . label ".source" . Util.del_ws_spc . store /[^;=# \t\n]+/ let shell_builtin_cmds = "ulimit" | "shift" | "exit" let eval = Util.indent . Util.del_str "eval" . Util.del_ws_spc . label "@eval" . store anyquot let alias = Util.indent . Util.del_str "alias" . Util.del_ws_spc . label "@alias" . store key_re . eq . [ label "value" . store anyquot ] let builtin = Util.indent . label "@builtin" . store shell_builtin_cmds . (Sep.cl_or_space . [ label "args" . sto_to_semicol ])? let keyword (kw:string) = Util.indent . Util.del_str kw let keyword_label (kw:string) (lbl:string) = keyword kw . label lbl let return = Util.indent . label "@return" . Util.del_str "return" . ( Util.del_ws_spc . store Rx.integer )? let action (operator:string) (lbl:string) (sto:lens) = let sp = Rx.cl_or_opt_space | /[ \t\n]+/ in [ del (sp . operator . sp) (" " . operator . " ") . label ("@".lbl) . sto ] let action_pipe = action "|" "pipe" let action_and = action "&&" "and" let action_or = action "||" "or" let condition = let cond (start:string) (end:string) = [ label "type" . store start ] . Util.del_ws_spc . sto_to_semicol . Util.del_ws_spc . Util.del_str end . ( action_and sto_to_semicol | action_or sto_to_semicol )* in Util.indent . label "@condition" . (cond "[" "]" | cond "[[" "]]") (* Entry types *) let entry_eol_item (item:lens) = [ item . comment_or_eol ] let entry_item (item:lens) = [ item ] let entry_eol_nocommand = entry_eol_item source | entry_eol_item kv | entry_eol_item unset | entry_eol_item bare_export | entry_eol_item builtin | entry_eol_item return | entry_eol_item condition | entry_eol_item eval | entry_eol_item alias let entry_noeol_nocommand = entry_item source | entry_item kv | entry_item unset | entry_item bare_export | entry_item builtin | entry_item return | entry_item condition | entry_item eval | entry_item alias (* Command *) let rec command = let env = [ key key_re . eq . store anyquot . Sep.cl_or_space ] in let reserved_key = /exit|shift|return|ulimit|unset|export|source|\.|if|for|select|while|until|then|else|fi|done|case|eval|alias/ in let word = /\$?[-A-Za-z0-9_.\/]+/ in let entry_eol = entry_eol_nocommand | entry_eol_item command in let entry_noeol = entry_noeol_nocommand | entry_item command in let entry = entry_eol | entry_noeol in let pipe = action_pipe (entry_eol_item command | entry_item command) in let and = action_and entry in let or = action_or entry in Util.indent . label "@command" . env* . store (word - reserved_key) . [ Sep.cl_or_space . label "@arg" . sto_to_semicol]? . ( pipe | and | or )? let entry_eol = entry_eol_nocommand | entry_eol_item command let entry_noeol = entry_noeol_nocommand | entry_item command (************************************************************************ * Group: CONDITIONALS AND LOOPS *************************************************************************) let generic_cond_start (start_kw:string) (lbl:string) (then_kw:string) (contents:lens) = keyword_label start_kw lbl . Sep.space . sto_to_semicol . ( action_and sto_to_semicol | action_or sto_to_semicol )* . semicol_eol . keyword then_kw . eol . contents let generic_cond (start_kw:string) (lbl:string) (then_kw:string) (contents:lens) (end_kw:string) = [ generic_cond_start start_kw lbl then_kw contents . keyword end_kw . comment_or_eol ] let cond_if (entry:lens) = let elif = [ generic_cond_start "elif" "@elif" "then" entry+ ] in let else = [ keyword_label "else" "@else" . eol . entry+ ] in generic_cond "if" "@if" "then" (entry+ . elif* . else?) "fi" let loop_for (entry:lens) = generic_cond "for" "@for" "do" entry+ "done" let loop_while (entry:lens) = generic_cond "while" "@while" "do" entry+ "done" let loop_until (entry:lens) = generic_cond "until" "@until" "do" entry+ "done" let loop_select (entry:lens) = generic_cond "select" "@select" "do" entry+ "done" let case (entry:lens) (entry_noeol:lens) = let pattern = [ label "@pattern" . sto_to_semicol . Sep.opt_space ] in let case_entry = [ label "@case_entry" . Util.indent . pattern . (Util.del_str "|" . Sep.opt_space . pattern)* . Util.del_str ")" . eol . entry* . entry_noeol? . Util.indent . Util.del_str ";;" . eol ] in [ keyword_label "case" "@case" . Sep.space . store (char+ | ("\"" . char+ . "\"")) . del /[ \t\n]+/ " " . Util.del_str "in" . eol . (empty* . comment* . case_entry)* . empty* . comment* . keyword "esac" . comment_or_eol ] let subshell (entry:lens) = [ Util.indent . label "@subshell" . Util.del_str "{" . brace_eol . entry+ . Util.indent . Util.del_str "}" . eol ] let function (entry:lens) (start_kw:string) (end_kw:string) = [ Util.indent . label "@function" . del /(function[ \t]+)?/ "" . store Rx.word . del /[ \t]*\(\)/ "()" . (comment_eol|brace_eol) . Util.del_str start_kw . brace_eol . entry+ . Util.indent . Util.del_str end_kw . eol ] let rec rec_entry = let entry = comment | entry_eol | rec_entry in cond_if entry | loop_for entry | loop_select entry | loop_while entry | loop_until entry | case entry entry_noeol | function entry "{" "}" | function entry "(" ")" | subshell entry let lns_norec = del_empty* . (comment | entry_eol) * let lns = del_empty* . (comment | entry_eol | rec_entry) * let sc_incl (n:string) = (incl ("/etc/sysconfig/" . n)) let sc_excl (n:string) = (excl ("/etc/sysconfig/" . n)) let filter_sysconfig = sc_incl "*" . sc_excl "anaconda" . sc_excl "bootloader" . sc_excl "hw-uuid" . sc_excl "hwconf" . sc_excl "ip*tables" . sc_excl "ip*tables.save" . sc_excl "kernel" . sc_excl "*.pub" . sc_excl "sysstat.ioconf" . sc_excl "system-config-firewall" . sc_excl "system-config-securitylevel" . sc_incl "network/config" . sc_incl "network/dhcp" . sc_incl "network/dhcp6r" . sc_incl "network/dhcp6s" . sc_incl "network/ifcfg-*" . sc_incl "network/if-down.d/*" . sc_incl "network/ifroute-*" . sc_incl "network/if-up.d/*" . sc_excl "network/if-up.d/SuSEfirewall2" . sc_incl "network/providers/*" . sc_excl "network-scripts" . sc_incl "network-scripts/ifcfg-*" . sc_excl "rhn" . sc_incl "rhn/allowed-actions/*" . sc_excl "rhn/allowed-actions/script" . sc_incl "rhn/allowed-actions/script/*" . sc_incl "rhn/rhnsd" . sc_excl "SuSEfirewall2.d" . sc_incl "SuSEfirewall2.d/cobbler" . sc_incl "SuSEfirewall2.d/services/*" . sc_excl "SuSEfirewall2.d/services/TEMPLATE" . sc_excl "*.systemd" let filter_default = incl "/etc/default/*" . excl "/etc/default/grub_installdevice*" . excl "/etc/default/rmt" . excl "/etc/default/star" . excl "/etc/default/whoopsie" . incl "/etc/profile" . incl "/etc/profile.d/*" . excl "/etc/profile.d/*.csh" . excl "/etc/profile.d/*.tcsh" . excl "/etc/profile.d/csh.local" let filter_misc = incl "/etc/arno-iptables-firewall/debconf.cfg" . incl "/etc/conf.d/*" . incl "/etc/cron-apt/config" . incl "/etc/environment" . incl "/etc/firewalld/firewalld.conf" . incl "/etc/blkid.conf" . incl "/etc/adduser.conf" . incl "/etc/cowpoke.conf" . incl "/etc/cvs-cron.conf" . incl "/etc/cvs-pserver.conf" . incl "/etc/devscripts.conf" . incl "/etc/kamailio/kamctlrc" . incl "/etc/lbu/lbu.conf" . incl "/etc/lintianrc" . incl "/etc/lsb-release" . incl "/etc/os-release" . incl "/etc/periodic.conf" . incl "/etc/popularity-contest.conf" . incl "/etc/rc.conf" . incl "/etc/rc.conf.d/*" . incl "/etc/rc.conf.local" . incl "/etc/selinux/config" . incl "/etc/ucf.conf" . incl "/etc/locale.conf" . incl "/etc/vconsole.conf" . incl "/etc/byobu/*" let filter = filter_sysconfig . filter_default . filter_misc . Util.stdexcl let xfm = transform lns filter (* Local Variables: *) (* mode: caml *) (* End: *)