page%swap@Sun.COM (Bob Page) (05/12/89)
Submitted-by: grwalter@watmath.waterloo.edu (Fred Walter) Posting-number: Volume 89, Issue 134 Archive-name: editors/stevie36.5 # This is a shell archive. # Remove anything above and including the cut line. # Then run the rest of the file through 'sh'. # Unpacked files will be owned by you and have default permissions. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: SHell ARchive # Run the following text through 'sh' to create: # regexp.cat.uu # regexp.h # regmagic.h # regsub.c # s_io.c # screen.c # search.c # This is archive 5 of a 6-part kit. # This archive created: Thu May 11 19:41:28 1989 echo "extracting regexp.cat.uu" sed 's/^X//' << \SHAR_EOF > regexp.cat.uu X Xbegin 644 regexp.cat XM"@H*"E)%1T584"@S*2`@("`@("`@("`@("`@("!,:6)R87)Y($9U;F-T:6]NR XM<R`@("`@("`@("`@("`@(%)%1T584"@S*0H*"@I."$Y!"$%-"$U%"$4*("`@6 XM("!R96=C;VUP+"!R96=E>&5C+"!R96=S=6(L(')E9V5R<F]R("T@<F5G=6QA1 XM<B!E>'!R97-S:6]N"B`@("`@:&%N9&QE<@H*4PA360A93@A.3PA/4`A04PA3& XM20A)4PA3"B`@("`@(P@C:0AI;@AN8PAC;`AL=0AU9`AD90AE(#P(/'((<F4(Y XM96<(9V4(97@(>'`(<"X(+F@(:#X(/@H*("`@("!R"')E"&5G"&=E"&5X"'APO XM"'`@*@@J<@AR90AE9PAG8PAC;PAO;0AM<`AP*`@H90AE>`AX<`AP*0@I"B`@T XM("`@8PAC:`AH80AA<@AR("H(*F4(97@(>'`(<#L(.PH*("`@("!I"&EN"&YT. XM"'0@<@AR90AE9PAG90AE>`AX90AE8PAC*`@H<`AP<@AR;PAO9PAG+`@L(',(] XM<W0(='((<FD(:6X(;F<(9RD(*0H@("`@('((<F4(96<(9V4(97@(>'`(<"`JW XM""IP"'!R"')O"&]G"&<["#L*("`@("!C"&-H"&AA"&%R"'(@*@@J<PAS=`AT@ XM<@AR:0AI;@AN9PAG.P@["@H@("`@('((<F4(96<(9W,(<W4(=6((8B@(*'`(" XM<'((<F\(;V<(9RP(+"!S"'-O"&]U"'5R"')C"&-E"&4L""P@9`AD90AE<PASZ XM=`AT*0@I"B`@("`@<@AR90AE9PAG90AE>`AX<`AP("H(*G`(<'((<F\(;V<(? XM9SL(.PH@("`@(&,(8V@(:&$(87((<B`J""IS"'-O"&]U"'5R"')C"&-E"&4[T XM"#L*("`@("!C"&-H"&AA"&%R"'(@*@@J9`AD90AE<PAS=`AT.P@["@H@("`@7 XM('((<F4(96<(9V4(97((<G((<F\(;W((<B@(*&T(;7,(<V<(9RD(*0H@("`@2 XM(&,(8V@(:&$(87((<B`J""IM"&US"'-G"&<["#L*"D0(1$4(15,(4T,(0U((H XM4DD(25`(4%0(5$D(24\(3TX(3@H@("`@(%1H97-E(&9U;F-T:6]N<R!I;7!L6 XM96UE;G0*("`@("!?"&5?"&=?"')?"&5?"'`H,2DM<W1Y;&4*("`@("!R96=U6 XM;&%R(&5X<')E<W-I;VYS(&%N9"!S=7!P;W)T:6YG(&9A8VEL:71I97,N"@H@/ XM("`@(%\(4E\(95\(9U\(8U\(;U\(;5\(<`H@("`@(&-O;7!I;&5S(&$@<F5G# XM=6QA<B!E>'!R97-S:6]N(&EN=&\@82!S=')U8W1U<F4@;V8@='EP90H@("`@Q XM(%\(<E\(95\(9U\(95\(>%\(<"P*("`@("!A;F0@<F5T=7)N<R!A('!O:6YT< XM97(@=&\@:70N"B`@("`@5&AE('-P86-E(&AA<R!B965N(&%L;&]C871E9"!UP XM<VEN9PH@("`@(%\(;5\(85\(;%\(;%\(;U\(8R@S*0H@("`@(&%N9"!M87D@E XM8F4@<F5L96%S960@8GD*("`@("!?"&9?"')?"&5?"&4N"@H@("`@(%\(4E\(1 XM95\(9U\(95\(>%\(95\(8PH@("`@(&UA=&-H97,@82!.54PM=&5R;6EN871E) XM9"!?"'-?"'1?"')?"&E?"&Y?"&<@86=A:6YS="!T:&4@8V]M<&EL960@<F5GX XM=6QA<B!E>'!R97-S:6]N"B`@("`@:6X@7PAP7PAR7PAO7PAG+@H@("`@($ETN XM(')E='5R;G,@,2!F;W(@<W5C8V5S<R!A;F0@,"!F;W(@9F%I;'5R92P@86YD5 XM(&%D:G5S=',@=&AE(&-O;G1E;G1S(&]F"B`@("`@7PAP7PAR7PAO7PAG)W,@Z XM7PAS7PAT7PAA7PAR7PAT7PAP(&%N9"!?"&5?"&Y?"&1?"'`@*'-E92!B96QO% XM=RD@86-C;W)D:6YG;'DN"@H@("`@(%1H92!M96UB97)S(&]F(&$*("`@("!?< XM"')?"&5?"&=?"&5?"'A?"'`*("`@("!S=')U8W1U<F4@:6YC;'5D92!A="!LV XM96%S="!T:&4@9F]L;&]W:6YG("AN;W0@;F5C97-S87)I;'D@:6X@;W)D97(IV XM.@H*("`@("`@("`@(&-H87(@*G-T87)T<%M.4U5"15A073L*("`@("`@("`@6 XM(&-H87(@*F5N9'!;3E-50D584%T["@H@("`@('=H97)E"B`@("`@7PA.7PA3O XM7PA57PA"7PA%7PA87PA0"B`@("`@:7,@9&5F:6YE9"`H87,@,3`I(&EN('1HU XM92!H96%D97(@9FEL92X*"@H*1F]R;6%T=&5D(#@X+S$R+S,P("`@("`@("`@^ XM("`@;&]C86P@("`@("`@("`@("`@("`@("`@("`@("`@("`@(#$*#`H*"@I2, XM14=%6%`H,RD@("`@("`@("`@("`@("`@3&EB<F%R>2!&=6YC=&EO;G,@("`@K XM("`@("`@("`@("!214=%6%`H,RD*"@H*("`@("!/;F-E(&$@<W5C8V5S<V9UQ XM;"!?"')?"&5?"&=?"&5?"'A?"&5?"&,@:&%S(&)E96X@9&]N92!U<VEN9R!TV XM:&4@7PAR7PAE7PAG7PAE7PAX7PAP+`H@("`@(&5A8V@@7PAS7PAT7PAA7PAR_ XM7PAT7PAP+5\(95\(;E\(9%\(<"!P86ER(&1E<V-R:6)E<R!O;F4@<W5B<W1RG XM:6YG"B`@("`@=VET:&EN('1H92!?"'-?"'1?"')?"&E?"&Y?"&<L"B`@("`@3 XM=VET:"!T:&4@7PAS7PAT7PAA7PAR7PAT7PAP('!O:6YT:6YG('1O('1H92!FW XM:7)S="!C:&%R86-T97(@;V8@=&AE('-U8G-T<FEN9R!A;F0*("`@("!T:&4@$ XM7PAE7PAN7PAD7PAP('!O:6YT:6YG('1O('1H92!F:7)S="!C:&%R86-T97(@D XM9F]L;&]W:6YG('1H92!S=6)S=')I;F<N"B`@("`@5&AE(#!T:"!S=6)S=')I$ XM;F<@:7,@=&AE('-U8G-T<FEN9R!O9B!?"'-?"'1?"')?"&E?"&Y?"&<@=&AAF XM="!M871C:&5D('1H92!W:&]L90H@("`@(')E9W5L87(@97AP<F5S<VEO;BX*. XM("`@("!4:&4@;W1H97)S(&%R92!T:&]S92!S=6)S=')I;F=S('1H870@;6%TX XM8VAE9"!P87)E;G1H97-I>F5D(&5X<')E<W-I;VYS"B`@("`@=VET:&EN('1H& XM92!R96=U;&%R(&5X<')E<W-I;VXL('=I=&@@<&%R96YT:&5S:7IE9"!E>'!RD XM97-S:6]N<R!N=6UB97)E9`H@("`@(&EN(&QE9G0M=&\M<FEG:'0@;W)D97(@Y XM;V8@=&AE:7(@;W!E;FEN9R!P87)E;G1H97-E<RX*"B`@("`@7PA27PAE7PAG8 XM7PAS7PAU7PAB"B`@("`@8V]P:65S(%\(<U\(;U\(=5\(<E\(8U\(92!T;R!?) XM"&1?"&5?"'-?"'0L(&UA:VEN9R!S=6)S=&ET=71I;VYS(&%C8V]R9&EN9R!T> XM;R!T:&4*("`@("!M;W-T(')E8V5N="!?"')?"&5?"&=?"&5?"'A?"&5?"&,@2 XM<&5R9F]R;65D('5S:6YG(%\(<%\(<E\(;U\(9RX*("`@("!%86-H(&EN<W1A& XM;F-E(&]F(&`F)R!I;B!?"'-?"&]?"'5?"')?"&-?"&4@:7,@<F5P;&%C960@& XM8GD@=&AE('-U8G-T<FEN9PH@("`@(&EN9&EC871E9"!B>2!?"'-?"'1?"&%?# XM"')?"'1?"'!;7P@P72!A;F0*("`@("!?"&5?"&Y?"&1?"'!;7P@P72X*("`@B XM("!%86-H(&EN<W1A;F-E(&]F(&!<7PAN)RP@=VAE<F4@7PAN(&ES(&$@9&EG@ XM:70L(&ES(')E<&QA8V5D(&)Y"B`@("`@=&AE('-U8G-T<FEN9R!I;F1I8V%T( XM960@8GD*("`@("!?"'-?"'1?"&%?"')?"'1?"'!;7PAN72!A;F0*("`@("!?? XM"&5?"&Y?"&1?"'!;7PAN72X*("`@("!4;R!G970@82!L:71E<F%L(&`F)R!O6 XM<B!@7%\(;B<@:6YT;R!?"&1?"&5?"'-?"'0L('!R969I>"!I="!W:71H(&!<? XM)SL*("`@("!T;R!G970@82!L:71E<F%L(&!<)R!P<F5C961I;F<@8"8G(&]R_ XM(&!<7PAN)RP@<')E9FEX(&ET('=I=&@*("`@("!A;F]T:&5R(&!<)RX*"B`@K XM("`@7PA27PAE7PAG7PAE7PAR7PAR7PAO7PAR"B`@("`@:7,@8V%L;&5D('=HJ XM96YE=F5R(&%N(&5R<F]R(&ES(&1E=&5C=&5D(&EN(%\(<E\(95\(9U\(8U\(7 XM;U\(;5\(<"P@7PAR7PAE7PAG7PAE7PAX7PAE7PAC+`H@("`@(&]R(%\(<E\(Q XM95\(9U\(<U\(=5\(8BX*("`@("!4:&4@9&5F875L="!?"')?"&5?"&=?"&5?N XM"')?"')?"&]?"'(@=W)I=&5S('1H92!S=')I;F<@7PAM7PAS7PAG+`H@("`@J XM('=I=&@@82!S=6ET86)L92!I;F1I8V%T;W(@;V8@;W)I9VEN+`H@("`@(&]N# XM('1H92!S=&%N9&%R9`H@("`@(&5R<F]R(&]U='!U=`H@("`@(&%N9"!I;G9OP XM:V5S(%\(95\(>%\(:5\(="@R*2X*("`@("!?"%)?"&5?"&=?"&5?"')?"')?$ XM"&]?"'(*("`@("!C86X@8F4@<F5P;&%C960@8GD@=&AE('5S97(@:68@;W1H( XM97(@86-T:6]N<R!A<F4@9&5S:7)A8FQE+@H*4@A210A%1PA'50A53`A,00A!] XM4@A2($4(15@(6%`(4%((4D4(15,(4U,(4TD(24\(3TX(3B!3"%-9"%E."$Y4\ XM"%1!"$%8"%@*("`@("!!(')E9W5L87(@97AP<F5S<VEO;B!I<R!Z97)O(&]RH XM(&UO<F4@7PAB7PAR7PAA7PAN7PAC7PAH7PAE7PAS+"!S97!A<F%T960@8GD@1 XM8'PG+@H@("`@($ET(&UA=&-H97,@86YY=&AI;F<@=&AA="!M871C:&5S(&]NR XM92!O9B!T:&4@8G)A;F-H97,N"@H@("`@($$@8G)A;F-H(&ES('IE<F\@;W(@/ XM;6]R92!?"'!?"&E?"&5?"&-?"&5?"',L(&-O;F-A=&5N871E9"X*("`@("!), XM="!M871C:&5S(&$@;6%T8V@@9F]R('1H92!F:7)S="P@9F]L;&]W960@8GD@Z XM82!M871C:"!F;W(@=&AE('-E8V]N9"P@971C+@H*("`@("!!('!I96-E(&ES_ XM(&%N(%\(85\(=%\(;U\(;2!P;W-S:6)L>2!F;VQL;W=E9"!B>2!@*B<L(&`K0 XM)RP@;W(@8#\G+@H@("`@($%N(&%T;VT@9F]L;&]W960@8GD@8"HG(&UA=&-H' XM97,@82!S97%U96YC92!O9B`P(&]R(&UO<F4@;6%T8VAE<R!O9B!T:&4@871OJ XM;2X*("`@("!!;B!A=&]M(&9O;&QO=V5D(&)Y(&`K)R!M871C:&5S(&$@<V5Q] XM=65N8V4@;V8@,2!O<B!M;W)E(&UA=&-H97,@;V8@=&AE(&%T;VTN"B`@("`@N XM06X@871O;2!F;VQL;W=E9"!B>2!@/R<@;6%T8VAE<R!A(&UA=&-H(&]F('1H! XM92!A=&]M+"!O<B!T:&4@;G5L;"!S=')I;F<N"@H@("`@($%N(&%T;VT@:7,@4 XM82!R96=U;&%R(&5X<')E<W-I;VX@:6X@<&%R96YT:&5S97,@*&UA=&-H:6YGO XM(&$@;6%T8V@@9F]R('1H90H@("`@(')E9W5L87(@97AP<F5S<VEO;BDL(&$@X XM7PAR7PAA7PAN7PAG7PAE("AS964@8F5L;W<I+"!@+B<*("`@("`H;6%T8VAI` XM;F<@86YY('-I;F=L92!C:&%R86-T97(I+"!@7B<@*&UA=&-H:6YG('1H92!N( XM=6QL('-T<FEN9R!A="!T:&4*("`@("!B96=I;FYI;F<@;V8@=&AE(&EN<'5T; XM('-T<FEN9RDL(&`D)R`H;6%T8VAI;F<@=&AE(&YU;&P@<W1R:6YG(&%T('1H. XM90H*"@I&;W)M871T960@.#@O,3(O,S`@("`@("`@("`@("!L;V-A;"`@("`@2 XM("`@("`@("`@("`@("`@("`@("`@("`@,@H,"@H*"E)%1T584"@S*2`@("`@? XM("`@("`@("`@("!,:6)R87)Y($9U;F-T:6]N<R`@("`@("`@("`@("`@(%)%% XM1T584"@S*0H*"@H@("`@(&5N9"!O9B!T:&4@:6YP=70@<W1R:6YG*2P@82!@J XM7"<@9F]L;&]W960@8GD@82!S:6YG;&4@8VAA<F%C=&5R("AM871C:&EN9PH@G XM("`@('1H870@8VAA<F%C=&5R*2P@;W(@82!S:6YG;&4@8VAA<F%C=&5R('=I$ XM=&@@;F\@;W1H97(@<VEG;FEF:6-A;F-E"B`@("`@*&UA=&-H:6YG('1H870@L XM8VAA<F%C=&5R*2X*"B`@("`@02!?"')?"&%?"&Y?"&=?"&4@:7,@82!S97%U$ XM96YC92!O9B!C:&%R86-T97)S(&5N8VQO<V5D(&EN(&!;72<N"B`@("`@270@( XM;F]R;6%L;'D@;6%T8VAE<R!A;GD@<VEN9VQE(&-H87)A8W1E<B!F<F]M('1H: XM92!S97%U96YC92X*("`@("!)9B!T:&4@<V5Q=65N8V4@8F5G:6YS('=I=&@@3 XM8%XG+`H@("`@(&ET(&UA=&-H97,@86YY('-I;F=L92!C:&%R86-T97(@7PANI XM7PAO7PAT(&9R;VT@=&AE(')E<W0@;V8@=&AE('-E<75E;F-E+@H@("`@($EF: XM('1W;R!C:&%R86-T97)S(&EN('1H92!S97%U96YC92!A<F4@<V5P87)A=&5D\ XM(&)Y(&`M)RP@=&AI<R!I<R!S:&]R=&AA;F0*("`@("!F;W(@=&AE(&9U;&P@_ XM;&ES="!O9B!!4T-)22!C:&%R86-T97)S(&)E='=E96X@=&AE;0H@("`@("AE) XM+F<N(&!;,"TY72<@;6%T8VAE<R!A;GD@9&5C:6UA;"!D:6=I="DN"B`@("`@& XM5&\@:6YC;'5D92!A(&QI=&5R86P@8%TG(&EN('1H92!S97%U96YC92P@;6%KO XM92!I="!T:&4@9FER<W0@8VAA<F%C=&5R"B`@("`@*&9O;&QO=VEN9R!A('!O[ XM<W-I8FQE(&!>)RDN"B`@("`@5&\@:6YC;'5D92!A(&QI=&5R86P@8"TG+"!MJ XM86ME(&ET('1H92!F:7)S="!O<B!L87-T(&-H87)A8W1E<BX*"D$(04T(34((Q XM0DD(24<(1U4(54D(250(5%D(60H@("`@($EF(&$@<F5G=6QA<B!E>'!R97-S^ XM:6]N(&-O=6QD(&UA=&-H('1W;R!D:69F97)E;G0@<&%R=',@;V8@=&AE(&EN2 XM<'5T('-T<FEN9RP*("`@("!I="!W:6QL(&UA=&-H('1H92!O;F4@=VAI8V@@> XM8F5G:6YS(&5A<FQI97-T+@H@("`@($EF(&)O=&@@8F5G:6X@:6X@=&AE('-AV XM;64@<&QA8V4@("`@8G5T(&UA=&-H(&1I9F9E<F5N="!L96YG=&AS+"!O<B!M5 XM871C:`H@("`@('1H92!S86UE(&QE;F=T:"!I;B!D:69F97)E;G0@=V%Y<RP@Q XM;&EF92!G971S(&UE<W-I97(L(&%S(&9O;&QO=W,N"@H@("`@($EN(&=E;F5R; XM86PL('1H92!P;W-S:6)I;&ET:65S(&EN(&$@;&ES="!O9B!B<F%N8VAE<R!AM XM<F4@8V]N<VED97)E9"!I;@H@("`@(&QE9G0M=&\M<FEG:'0@;W)D97(L('1HB XM92!P;W-S:6)I;&ET:65S(&9O<B!@*B<L(&`K)RP@86YD(&`_)R!A<F4*("`@E XM("!C;VYS:61E<F5D(&QO;F=E<W0M9FER<W0L(&YE<W1E9"!C;VYS=')U8W1S8 XM(&%R92!C;VYS:61E<F5D(&9R;VT@=&AE"B`@("`@;W5T97)M;W-T(&EN+"!A- XM;F0@8V]N8V%T96YA=&5D(&-O;G-T<G5C=',@87)E(&-O;G-I9&5R960@;&5F" XM=&UO<W0M9FER<W0N"B`@("`@5&AE(&UA=&-H('1H870@=VEL;"!B92!C:&]S/ XM96X@:7,@=&AE(&]N92!T:&%T('5S97,@=&AE(&5A<FQI97-T"B`@("`@<&]S9 XM<VEB:6QI='D@:6X@=&AE(&9I<G-T(&-H;VEC92!T:&%T(&AA<R!T;R!B92!MX XM861E+@H@("`@($EF('1H97)E(&ES(&UO<F4@=&AA;B!O;F4@8VAO:6-E+"!TP XM:&4@;F5X="!W:6QL(&)E(&UA9&4@:6X@=&AE('-A;64@;6%N;F5R"B`@("`@+ XM*&5A<FQI97-T('!O<W-I8FEL:71Y*2!S=6)J96-T('1O('1H92!D96-I<VEOY XM;B!O;B!T:&4@9FER<W0@8VAO:6-E+@H@("`@($%N9"!S;R!F;W)T:"X*"B`@1 XM("`@1F]R(&5X86UP;&4L(&`H86)\82EB*F,G(&-O=6QD(&UA=&-H(&!A8F,GW XM(&EN(&]N92!O9B!T=V\@=V%Y<RX*("`@("!4:&4@9FER<W0@8VAO:6-E(&EST XM(&)E='=E96X@8&%B)R!A;F0@8&$G.R!S:6YC92!@86(G(&ES(&5A<FQI97(L2 XM(&%N9"!D;V5S"B`@("`@;&5A9"!T;R!A('-U8V-E<W-F=6P@;W9E<F%L;"!MD XM871C:"P@:70@:7,@8VAO<V5N+@H@("`@(%-I;F-E('1H92!@8B<@:7,@86QRT XM96%D>2!S<&]K96X@9F]R+`H@("`@('1H92!@8BHG(&UU<W0@;6%T8V@@:71S* XM(&QA<W0@<&]S<VEB:6QI='DM+71H92!E;7!T>2!S=')I;F<M+7-I;F-E"B`@& XM("`@:70@;75S="!R97-P96-T('1H92!E87)L:65R(&-H;VEC92X*"B`@("`@. XM26X@=&AE('!A<G1I8W5L87(@8V%S92!W:&5R92!N;R!@?"=S(&%R92!P<F5SK XM96YT(&%N9"!T:&5R92!I<R!O;FQY(&]N90H@("`@(&`J)RP@8"LG+"!O<B!@8 XM/R<L('1H92!N970@969F96-T(&ES('1H870@=&AE(&QO;F=E<W0@<&]S<VEBA XM;&4*("`@("!M871C:"!W:6QL(&)E(&-H;W-E;BX*("`@("!3;R!@86(J)RP@A XM<')E<V5N=&5D('=I=&@@8'AA8F)B8GDG+"!W:6QL(&UA=&-H(&!A8F)B8B<N6 XM"B`@("`@3F]T92!T:&%T(&EF(&!A8BHG(&ES('1R:65D(&%G86EN<W0@8'AAH XM8GEA8F)B>B<L(&ET"B`@("`@=VEL;"!M871C:"!@86(G(&IU<W0@869T97(@= XM8'@G+"!D=64@=&\@=&AE(&)E9VEN<RUE87)L:65S="!R=6QE+@H@("`@("A)L XM;B!E9F9E8W0L('1H92!D96-I<VEO;B!O;B!W:&5R92!T;R!S=&%R="!T:&4@` XM;6%T8V@@:7,@=&AE(&9I<G-T(&-H;VEC90H@("`@('1O(&)E(&UA9&4L(&AE! XM;F-E('-U8G-E<75E;G0@8VAO:6-E<R!M=7-T(')E<W!E8W0@:70@979E;B!IV XM9B!T:&ES(&QE861S('1H96T*("`@("!T;R!L97-S+7!R969E<G)E9"!A;'1E+ XM<FYA=&EV97,N*0H*4PA310A%10A%($$(04P(3%,(4T\(3PH@("`@(&5G<F5P$ XM*#$I+"!E>'!R*#$I"@H*"@H*1F]R;6%T=&5D(#@X+S$R+S,P("`@("`@("`@% XM("`@;&]C86P@("`@("`@("`@("`@("`@("`@("`@("`@("`@(#,*#`H*"@I2. XM14=%6%`H,RD@("`@("`@("`@("`@("`@3&EB<F%R>2!&=6YC=&EO;G,@("`@K XM("`@("`@("`@("!214=%6%`H,RD*"@H*1`A$20A)00A!1PA'3@A.3PA/4PA39 XM5`A420A)0PA#4PA3"B`@("`@7PA27PAE7PAG7PAC7PAO7PAM7PAP(')E='5R@ XM;G,@3E5,3"!F;W(@82!F86EL=7)E"B`@("`@*%\(<E\(95\(9U\(95\(<E\(] XM<E\(;U\(<B!P97)M:71T:6YG*2P*("`@("!W:&5R92!F86EL=7)E<R!A<F4@1 XM<WEN=&%X(&5R<F]R<RP@97AC965D:6YG(&EM<&QE;65N=&%T:6]N(&QI;6ETA XM<RP*("`@("!O<B!A<'!L>6EN9R!@*R<@;W(@8"HG('1O(&$@<&]S<VEB;'DM8 XM;G5L;"!O<&5R86YD+@H*2`A(20A)4PA35`A43PA/4@A260A9"B`@("`@0F]TQ XM:"!C;V1E(&%N9"!M86YU86P@<&%G92!W97)E"B`@("`@=W)I='1E;B!A="!5% XM(&]F(%0N"B`@("`@5&AE>2!A<F4@:6YT96YD960@=&\@8F4@8V]M<&%T:6)LC XM92!W:71H('1H92!"96QL(%8X(%\(<E\(95\(9U\(95\(>%\(<"@S*2P*("`@> XM("!B=70@87)E(&YO="!D97)I=F5D(&9R;VT@0F5L;"!C;V1E+@H*0@A"50A5% XM1PA'4PA3"B`@("`@16UP='D@8G)A;F-H97,@86YD(&5M<'1Y(')E9W5L87(@W XM97AP<F5S<VEO;G,@87)E(&YO="!P;W)T86)L92!T;R!6."X*"B`@("`@5&AEY XM(')E<W1R:6-T:6]N(&%G86EN<W0*("`@("!A<'!L>6EN9R!@*B<@;W(@8"LG/ XM('1O(&$@<&]S<VEB;'DM;G5L;"!O<&5R86YD(&ES(&%N(&%R=&EF86-T(&]F8 XM('1H90H@("`@('-I;7!L:7-T:6,@:6UP;&5M96YT871I;VXN"@H@("`@($1OG XM97,@;F]T('-U<'!O<G0@7PAE7PAG7PAR7PAE7PAP)W,@;F5W;&EN92US97!A^ XM<F%T960@8G)A;F-H97,["B`@("`@;F5I=&AE<B!D;V5S('1H92!6."!?"')?\ XM"&5?"&=?"&5?"'A?"'`H,RDL('1H;W5G:"X*"B`@("`@1'5E('1O(&5M<&AA* XM<VES(&]N"B`@("`@8V]M<&%C=&YE<W,@86YD('-I;7!L:6-I='DL"B`@("`@F XM:70G<R!N;W0@<W1R:6MI;F=L>2!F87-T+@H@("`@($ET(&1O97,@9VEV92!SD XM<&5C:6%L(&%T=&5N=&EO;B!T;R!H86YD;&EN9R!S:6UP;&4@8V%S97,@<75I4 XM8VML>2X*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@H*"@I&;W)M871T960@3 XM.#@O,3(O,S`@("`@("`@("`@("!L;V-A;"`@("`@("`@("`@("`@("`@("`@? X+("`@("`@("`@-`H@^ X`` Xend Xsize 8651 SHAR_EOF echo "extracting regexp.h" sed 's/^X//' << \SHAR_EOF > regexp.h X/* X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE X * X * This is NOT the original regular expression code as written by X * Henry Spencer. This code has been modified specifically for use X * with the STEVIE editor, and should not be used apart from compiling X * STEVIE. If you want a good regular expression library, get the X * original code. The copyright notice that follows is from the X * original. X * X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE X * X * Definitions etc. for regexp(3) routines. X * X * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof], X * not the System V one. X */ X#define NSUBEXP 10 Xtypedef struct regexp { X char *startp[NSUBEXP]; X char *endp[NSUBEXP]; X char regstart; /* Internal use only. */ X char reganch; /* Internal use only. */ X char *regmust; /* Internal use only. */ X int regmlen; /* Internal use only. */ X char program[1]; /* Unwarranted chumminess with compiler. */ X} regexp; X Xextern regexp *regcomp(); Xextern int regexec(); Xextern void regsub(); Xextern void regerror(); X X#ifndef ORIGINAL Xextern int reg_ic; /* set non-zero to ignore case in searches */ X#endif SHAR_EOF echo "extracting regmagic.h" sed 's/^X//' << \SHAR_EOF > regmagic.h X/* X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE X * X * This is NOT the original regular expression code as written by X * Henry Spencer. This code has been modified specifically for use X * with the STEVIE editor, and should not be used apart from compiling X * STEVIE. If you want a good regular expression library, get the X * original code. The copyright notice that follows is from the X * original. X * X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE X * X * The first byte of the regexp internal "program" is actually this magic X * number; the start node begins in the second byte. X */ X#define MAGIC 0234 SHAR_EOF echo "extracting regsub.c" sed 's/^X//' << \SHAR_EOF > regsub.c X/* X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE X * X * This is NOT the original regular expression code as written by X * Henry Spencer. This code has been modified specifically for use X * with the STEVIE editor, and should not be used apart from compiling X * STEVIE. If you want a good regular expression library, get the X * original code. The copyright notice that follows is from the X * original. X * X * NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE X * X * regsub X * X * Copyright (c) 1986 by University of Toronto. X * Written by Henry Spencer. Not derived from licensed software. X * X * Permission is granted to anyone to use this software for any X * purpose on any computer system, and to redistribute it freely, X * subject to the following restrictions: X * X * 1. The author is not responsible for the consequences of use of X * this software, no matter how awful, even if they arise X * from defects in it. X * X * 2. The origin of this software must not be misrepresented, either X * by explicit claim or by omission. X * X * 3. Altered versions must be plainly marked as such, and must not X * be misrepresented as being the original software. X * X * $Log: regsub.c,v $ X * Revision 1.2 88/04/28 08:11:25 tony X * First modification of the regexp library. Added an external variable X * 'reg_ic' which can be set to indicate that case should be ignored. X * Added a new parameter to regexec() to indicate that the given string X * comes from the beginning of a line and is thus eligible to match X * 'beginning-of-line'. X * X */ X X#include "env.h" X X#ifdef MEGAMAX Xoverlay "regexp" X#endif X X#include <stdio.h> X#include "regexp.h" X#include "regmagic.h" X X#ifndef CHARBITS X#define UCHARAT(p) ((int)*(unsigned char *)(p)) X#else X#define UCHARAT(p) ((int)*(p)&CHARBITS) X#endif X X/* X - regsub - perform substitutions after a regexp match X */ Xvoid Xregsub(prog, source, dest) X regexp *prog; X char *source; X char *dest; X{ X register char *src; X register char *dst; X register char c; X register int no; X register int len; X extern char *strncpy(); X X if (prog == NULL || source == NULL || dest == NULL) { X regerror("NULL parm to regsub"); X return; X } X if (UCHARAT(prog->program) != MAGIC) { X regerror("damaged regexp fed to regsub"); X return; X } X src = source; X dst = dest; X while ((c = *src++) != '\0') { X if (c == '&') X no = 0; X else if (c == '\\' && '0' <= *src && *src <= '9') X no = *src++ - '0'; X else X no = -1; X if (no < 0) { /* Ordinary character. */ X if (c == '\\' && (*src == '\\' || *src == '&')) X c = *src++; X *dst++ = c; X } else if (prog->startp[no] != NULL && prog->endp[no] != NULL) { X len = prog->endp[no] - prog->startp[no]; X (void) strncpy(dst, prog->startp[no], len); X dst += len; X if (len != 0 && *(dst - 1) == '\0') { /* strncpy hit NUL. */ X regerror("damaged match string"); X return; X } X } X } X *dst = '\0'; X} SHAR_EOF echo "extracting s_io.c" sed 's/^X//' << \SHAR_EOF > s_io.c X/* X * s_io() - routines that do screen I/O or effect what we think is X * on the screen. X * X * By G. R. (Fred) Walter watmath!watcgl!grwalter X */ X X#include "stevie.h" X X/* X * screen_ins(row, nlines, total_rows) - insert 'nlines' lines at 'row' X * X * NOTE: this routine assumes it is called with valid arguments. X */ X Xstatic void Xscreen_ins(row, nlines, total_rows) X int row; X int nlines; X int total_rows; X{ X if (nlines < 1 || (row + nlines) > total_rows) X return; X X#ifndef T_IL_B X { X int i; X X for (i = 0; i < nlines; i++) { X windgoto(row, 0); X outstr(T_IL); X } X } X#else X windgoto(row, 0); X outstr(T_IL); X if (nlines >= 10) X outchar((char) (nlines / 10 + '0')); X outchar((char) (nlines % 10 + '0')); X outstr(T_IL_B); X#endif X X /* delete any garbage that may have been shifted to the status line */ X windgoto(total_rows - 1, 0); X outstr(T_EL); X} X X/* X * screen_del(row, nlines, total_rows) - delete 'nlines' lines at 'row' X * X * NOTE: this routine assumes it is called with valid arguments. X */ X Xstatic void Xscreen_del(row, nlines, total_rows) X int row; X int nlines; X int total_rows; X{ X if (nlines < 1 || (row + nlines) > total_rows) X return; X X /* delete any garbage that may have been on the status line */ X windgoto(total_rows - 1, 0); X outstr(T_EL); X X#ifndef T_DL_B X { X int i; X X for (i = 0; i < nlines; i++) { X windgoto(row, 0); X outstr(T_DL); /* delete a line */ X } X } X#else X windgoto(row, 0); X outstr(T_DL); X if (nlines >= 10) X outchar((char) (nlines / 10 + '0')); X outchar((char) (nlines % 10 + '0')); X outstr(T_DL_B); X#endif X} X X/* X * screen_refresh() X * X * Based on the current value of Topchar, refresh the contents of the screen X * and update Botchar. X */ X Xstatic void Xscreen_refresh(type) X int type; X{ X char *ptr; X int total_rows; X int row; X int col; X LINE *memp; X LPtr start; X bool_t off_top; X bool_t done; /* if TRUE, we hit the end of the file */ X bool_t didline; /* if TRUE, we finished the last line */ X int lno; /* number of the line we're doing */ X int coff; X int idx; X int i; X int j; X X if (NumLineSizes <= 0) X type = NOT_VALID; X X if (!RedrawingDisabled) X outstr(T_CI); X X off_top = FALSE; X idx = 0; X row = 0; X total_rows = Rows - 1; X memp = Topchar->linep; X X if ((type == VALID) || (type == VALID_TO_CURSCHAR)) { X j = -1; X for (i = 0; i < NumLineSizes; i++) { X if (LinePointers[i] == memp) { X j = i; X break; X } X row += LineSizes[i]; X } X if (j == -1) { X /* Are we off the top of the screen by one line ? */ X if (memp->next == LinePointers[0]) { X i = plines(Topchar->linep->s); X if (i < (total_rows)) { X off_top = TRUE; X for (idx = NumLineSizes; idx > 0; idx--) { X LinePointers[idx] = LinePointers[idx - 1]; X LineSizes[idx] = LineSizes[idx - 1]; X } X LineSizes[idx] = (char) i; X if (!RedrawingDisabled) X screen_ins(0, i, Rows); X } X } X row = 0; X } else if (j == 0 && type == VALID) { X if (!RedrawingDisabled) X outstr(T_CV); X return; X } else { X if (!RedrawingDisabled) X screen_del(0, row, Rows); X row = 0; X for (;;) { X LineSizes[idx] = LineSizes[j]; X LinePointers[idx] = LinePointers[j]; X X if (type == VALID_TO_CURSCHAR) { X if (LinePointers[idx] == Curschar->linep) { X memp = LinePointers[idx]; X break; X } X } X j++; X if (j >= NumLineSizes) { X memp = LinePointers[idx]; X if (memp->next != Fileend->linep) { X row += LineSizes[idx]; X idx++; X memp = memp->next; X } X break; X } X row += LineSizes[idx]; X idx++; X } X } X } X coff = 0; X if (P(P_NU)) { X coff = 8; X start.linep = memp; X lno = cntllines(Filemem, &start); X } X didline = TRUE; X done = FALSE; X X for (;;) { X ptr = format_line(memp->s, &col); X i = 1 + ((col - 1) / Columns); X if ((row + i) <= total_rows) { X LinePointers[idx] = memp; X LineSizes[idx++] = (char) i; X if (!RedrawingDisabled) { X windgoto(row, 0); X X if (P(P_NU)) X outstr(mkline(lno++)); X outstr(ptr); X X j = col + coff; X col = j % Columns; X if ((col != 0) || (j == 0)) { X#ifdef T_END_L X windgoto(row + i - 1, col); X outstr(T_END_L); X#else X for (; col < Columns; col++) X outchar(' '); X#endif X } X } X row += i; X if (memp->next != Fileend->linep) { X memp = memp->next; X } else { X done = TRUE; X break; X } X if (off_top) X break; X } else { X didline = FALSE; X break; X } X } X X /* Do we have to do off the top of the screen processing ? */ X if (off_top && !done) { X row = 0; X for (idx = 0; idx <= NumLineSizes && row < total_rows; idx++) { X row += LineSizes[idx]; X } X X idx--; X X if (row < total_rows) { X done = TRUE; X idx++; X } else if (row > total_rows) { X row -= LineSizes[idx]; X didline = FALSE; X memp = LinePointers[idx]; X } else { X didline = TRUE; X memp = LinePointers[idx]->next; X idx++; X } X } X NumLineSizes = idx; X X /* X * If we didn't hit the end of the file, and we didn't finish the last X * line we were working on, then the line didn't fit. X */ X if (!done && !didline) { X if (!RedrawingDisabled) { X /* Clear the rest of the screen. */ X#ifdef T_END_D X windgoto(row, 0); X outstr(T_END_D); X#else X screen_del(row, total_rows - row, Rows); X windgoto(row, 0); X#endif X /* put '@'s on rows that are part of a line that's too long */ X for (; row < total_rows; row++) X outstr("@\n\r"); X } X Botchar->linep = memp; X } else { X if (!RedrawingDisabled && !off_top) { X /* Clear the rest of the screen. */ X#ifdef T_END_D X windgoto(row, 0); X outstr(T_END_D); X#else X screen_del(row, total_rows - row, Rows); X windgoto(row, 0); X#endif X /* put '~'s on rows that aren't part of the file. */ X for (; row < total_rows; row++) X outstr("~\n\r"); X } X if (done) /* we hit the end of the file */ X *Botchar = *Fileend; X else X Botchar->linep = memp; /* FIX - prev? */ X } X X if (!RedrawingDisabled) X outstr(T_CV); X} X X/* X * s_refresh() X * X * Based on the current value of Curschar, (if necessary) update Topchar and X * Botchar and refresh the screen contensts. X */ X Xvoid Xs_refresh(type) X int type; X{ X LPtr *p; X LPtr *pp; X int i; X int nlines; X int refreshed; X X refreshed = FALSE; X X if (bufempty()) { /* special case - file is empty */ X *Topchar = *Filemem; X *Curschar = *Filemem; X screen_refresh(NOT_VALID); X return; X } X if (NumLineSizes < 0) { X type = NOT_VALID; X } X if (type != VALID) { X screen_refresh(type); X refreshed = TRUE; X type = VALID; X } X if (LINEOF(Curschar) < LINEOF(Topchar)) { X nlines = cntllines(Curschar, Topchar); X /* X * if the cursor is above the top of the screen, put it at the top of X * the screen.. X */ X *Topchar = *Curschar; X Topchar->index = 0; X /* X * ... and, if we weren't very close to begin with, we scroll so that X * the line is close to the middle. X */ X if (nlines > Rows / 3) { X p = Topchar; X for (i = 0; i < Rows / 3; i += plines(p->linep->s)) { X pp = prevline(p); X if (pp == NULL) X break; X p = pp; X } X *Topchar = *p; X } X screen_refresh(VALID); X } else if (LINEOF(Curschar) >= LINEOF(Botchar)) { X nlines = cntllines(Botchar, Curschar); X /* X * If the cursor is off the bottom of the screen, put it at the top X * of the screen.. ... and back up X */ X if (nlines > Rows / 3) { X p = Curschar; X for (i = 0; i < (2 * Rows) / 3; i += plines(p->linep->s)) { X pp = prevline(p); X if (pp == NULL) X break; X p = pp; X } X *Topchar = *p; X } else { X scrollup(nlines); X } X screen_refresh(VALID); X } else if (refreshed == FALSE) { X screen_refresh(type); X } X /* Check if we are below Botchar (this can occur). */ X if (LINEOF(Curschar) == LINEOF(Botchar)) { X pp = nextline(Topchar); X if (pp != NULL) { X Topchar->linep = pp->linep; X screen_refresh(VALID); X } X } else if (LINEOF(Curschar) > LINEOF(Botchar)) { X nlines = cntllines(Botchar, Curschar); X /* X * If the cursor is off the bottom of the screen, put it at the top X * of the screen.. ... and back up X */ X if (nlines > Rows / 3) { X p = Curschar; X for (i = 0; i < (2 * Rows) / 3; i += plines(p->linep->s)) { X pp = prevline(p); X if (pp == NULL) X break; X p = pp; X } X *Topchar = *p; X } else { X scrollup(nlines); X } X screen_refresh(VALID); X } X} X X/* X * s_clear() - clear the screen and mark the stored information as invalid. X */ Xvoid Xs_clear() X{ X outstr(T_ED); /* clear the display */ X S_NOT_VALID; X} X X/* X * Update_Botchar() X * X * Based on the current value of Topchar update Botchar. X */ X Xvoid XUpdate_Botchar() X{ X int row; X LINE *memp; X int total_rows; X int i; X X row = 0; X total_rows = Rows - 1; X memp = Topchar->linep; X X for (;;) { X i = plines(memp->s); X if ((row + i) <= total_rows) { X row += i; X memp = memp->next; X if (memp == Fileend->linep) X break; X } else { X break; X } X } X Botchar->linep = memp; X X MustUpdateBotchar = FALSE; X} X X#ifdef DONTINCLUDEANYMORE X/* X * NotValidFromCurschar() X * X * Mark the lines in NumLinePointers and NumLineSizes from Curschar on as X * not valid. X */ X Xvoid XNotValidFromCurschar() X{ X register int idx; X register unsigned long num; X X S_VALID_TO_CURSCHAR; X X num = LINEOF(Curschar); X for (idx = 0; idx < NumLineSizes; idx++) { X if (LinePointers[idx]->num >= num) X break; X } X NumLineSizes = idx; X} X#endif SHAR_EOF echo "extracting screen.c" sed 's/^X//' << \SHAR_EOF > screen.c X/* X * STEVIE - Simply Try this Editor for VI Enthusiasts X * X * Code Contributions By : Tim Thompson twitch!tjt X * Tony Andrews onecom!wldrdg!tony X * G. R. (Fred) Walter watmath!watcgl!grwalter X */ X X#include "stevie.h" X X/* X * The following variable is set (in cursupdate) to the number of physical X * lines taken by the line the cursor is on. We use this to avoid extra calls X * to plines(). The optimized routine updateline() makes sure that the size of X * the cursor line hasn't changed. If so, lines below the cursor will move up X * or down and we need to call the routine s_refresh() to examine the X * entire screen. X */ Xstatic int Cline_size; /* size (in rows) of the cursor line */ Xstatic int Cline_row; /* starting row of the cursor line */ X X/* X * updateline() - like s_refresh() but only for cursor line X * X * This determines whether or not we need to call s_refresh() to examine X * the entire screen for changes. This occurs if the size of the cursor line X * (in rows) has changed. X */ Xstatic void Xupdateline() X{ X char *ptr; X int col; X int size; X int j; X X if (RedrawingDisabled) /* Is this the correct action ? */ X return; X X ptr = format_line(Curschar->linep->s, &col); X X size = 1 + ((col - 1) / Columns); X if (Cline_size == size) { X outstr(T_CI); X windgoto(Cline_row, 0); X if (P(P_NU)) { X /* X * This should be done more efficiently. X */ X outstr(mkline(cntllines(Filemem, Curschar))); X } X outstr(ptr); X X j = col + (P(P_NU) ? 8 : 0); X col = j % Columns; X if ((col != 0) || (j == 0)) { X#ifdef T_END_L X windgoto(Cline_row + size - 1, col); X outstr(T_END_L); X#else X for (; col < Columns; col++) X outchar(' '); X#endif X } X outstr(T_CV); X } else { X s_refresh(VALID_TO_CURSCHAR); X } X} X Xvoid Xcursupdate(type) X int type; X{ X register char c; X register int incr; X register int i; X register int didincr; X X if (MustUpdateBotchar == TRUE) X Update_Botchar(); X X if (NumLineSizes < 0) { X s_refresh(NOT_VALID); X } else { X if (LineNotValid == TRUE) X updateline(); X X if (type != UPDATE_CURSOR) { X s_refresh(type); X } else if (ValidToCurschar == TRUE) { X s_refresh(VALID_TO_CURSCHAR); X } else if (CheckTopcharAndBotchar == TRUE) { X s_refresh(VALID); X } X } X X CheckTopcharAndBotchar = FALSE; X MustUpdateBotchar = FALSE; X ValidToCurschar = FALSE; X LineNotValid = FALSE; X X Cursrow = Curscol = Cursvcol = i = 0; X for (i = 0; i < NumLineSizes; i++) { X if (LinePointers[i] == Curschar->linep) X break; X Cursrow += LineSizes[i]; X } X X if (P(P_NU)) X Curscol = 8; X X Cline_row = Cursrow; X Cline_size = LineSizes[i]; X X for (i = 0; i <= Curschar->index; i++) { X c = Curschar->linep->s[i]; X /* A tab gets expanded, depending on the current column */ X if (c == TAB && !P(P_LS)) X incr = P(P_TS) - (Cursvcol % P(P_TS)); X else X incr = chars[c].ch_size; X Curscol += incr; X Cursvcol += incr; X if (Curscol >= Columns) { X Curscol -= Columns; X Cursrow++; X didincr = TRUE; X } else X didincr = FALSE; X } X if (didincr) X Cursrow--; X X if (c == TAB && State == NORMAL && !P(P_LS)) { X Curscol--; X Cursvcol--; X } else { X Curscol -= incr; X Cursvcol -= incr; X } X if (Curscol < 0) X Curscol += Columns; X X if (set_want_col) { X Curswant = Cursvcol; X set_want_col = FALSE; X } X} SHAR_EOF echo "extracting search.c" sed 's/^X//' << \SHAR_EOF > search.c X/* X * STEVIE - Simply Try this Editor for VI Enthusiasts X * X * Code Contributions By : Tim Thompson twitch!tjt X * Tony Andrews onecom!wldrdg!tony X * G. R. (Fred) Walter watmath!watcgl!grwalter X */ X X#include "stevie.h" X/* modified Henry Spencer's regular expression routines */ X#include "regexp.h" X X#ifdef MEGAMAX Xoverlay "search" X#endif X X/* X * This file contains various searching-related routines. These fall into X * three groups: string searches (for /, ?, n, and N), character searches X * within a single line (for f, F, t, T, etc), and "other" kinds of searches X * like the '%' command, and 'word' searches. X */ X X/* X * String searches X * X * The actual searches are done using Henry Spencer's regular expression X * library. X */ X X#define BEGWORD "([^a-zA-Z0-9_]|^)" /* replaces "\<" in search strings */ X#define ENDWORD "([^a-zA-Z0-9_]|$)" /* likewise replaces "\>" */ X Xbool_t begword; /* does the search include a 'begin word' X * match */ X X/* X * mapstring(s) - map special backslash sequences X */ Xstatic char * Xmapstring(s) X register char *s; X{ X static char ns[MAX_COLUMNS + 1]; X register char *p; X X begword = FALSE; X X for (p = ns; *s; s++) { X if ((*s == '(') || (*s == ')')) { X *p++ = '\\'; X *p++ = *s; X continue; X } X if (*s != '\\') { /* not an escape */ X *p++ = *s; X continue; X } X switch (*++s) { X case '/': X *p++ = '/'; X break; X X case '<': X strcpy(p, BEGWORD); X p += strlen(BEGWORD); X begword = TRUE; X break; X X case '>': X strcpy(p, ENDWORD); X p += strlen(ENDWORD); X break; X X default: X *p++ = '\\'; X *p++ = *s; X break; X } X } X *p = NUL; X X return ns; X} X Xstatic LPtr * Xbcksearch(str) X char *str; X{ X static LPtr infile; X register LPtr *p; X regexp *prog; X register char *s; X register int i; X bool_t want_start = (*str == '^'); /* looking for start of line? */ X register char *match; X X /* make sure str isn't empty */ X if (str == NULL || *str == NUL) X return NULL; X X prog = regcomp(str); X if (prog == NULL) { X emsg("Invalid search string"); X return NULL; X } X p = Curschar; X dec(p); X X if (begword) /* so we don't get stuck on one match */ X dec(p); X X i = (want_start) ? 0 : p->index; X X do { X s = p->linep->s; X X if (regexec(prog, s, TRUE)) { /* match somewhere on line */ X X if (want_start) { /* could only have been one */ X infile.linep = p->linep; X infile.index = (int) (prog->startp[0] - s); X free((char *) prog); X return (&infile); X } X /* X * Now, if there are multiple matches on this line, we have to X * get the last one. Or the last one before the cursor, if we're X * on that line. X */ X X match = prog->startp[0]; X X while (regexec(prog, prog->endp[0], FALSE)) { X if ((i >= 0) && ((prog->startp[0] - s) > i)) X break; X match = prog->startp[0]; X } X X if ((i >= 0) && ((match - s) > i)) { X i = -1; X continue; X } X infile.linep = p->linep; X infile.index = (int) (match - s); X free((char *) prog); X return (&infile); X } X i = -1; X X } while ((p = prevline(p)) != NULL); X X /* X * If wrapscan isn't set, bag the search now X */ X if (!P(P_WS)) { X free((char *) prog); X return NULL; X } X /* search backward from the end of the file */ X p = prevline(Fileend); X do { X s = p->linep->s; X X if (regexec(prog, s, TRUE)) { /* match somewhere on line */ X X if (want_start) { /* could only have been one */ X infile.linep = p->linep; X infile.index = (int) (prog->startp[0] - s); X free((char *) prog); X return (&infile); X } X /* X * Now, if there are multiple matches on this line, we have to X * get the last one. X */ X X match = prog->startp[0]; X X while (regexec(prog, prog->endp[0], FALSE)) X match = prog->startp[0]; X X infile.linep = p->linep; X infile.index = (int) (match - s); X free((char *) prog); X return (&infile); X } X if (p->linep == Curschar->linep) X break; X X } while ((p = prevline(p)) != NULL); X X free((char *) prog); X return NULL; X} X Xstatic LPtr * Xfwdsearch(str) X char *str; X{ X static LPtr infile; X LPtr *p; X regexp *prog; X bool_t want_start = (*str == '^'); /* looking for start of line? */ X X char *s; X int i; X X prog = regcomp(str); X if (prog == NULL) { X emsg("Invalid search string"); X return NULL; X } X p = Curschar; X i = Curschar->index + 1; X do { X s = p->linep->s + i; X i = 0; X X if (regexec(prog, s, i == 0)) { /* got a match */ X /* X * If we wanted the start of a line and we aren't really there, X * then a match doesn't count. X */ X if (want_start && (s != p->linep->s)) X continue; X X infile.linep = p->linep; X infile.index = (int) (prog->startp[0] - p->linep->s); X free((char *) prog); X return (&infile); X } X } while ((p = nextline(p)) != NULL); X X /* X * If wrapscan isn't set, then don't scan from the beginning of the file. X * Just return failure here. X */ X if (!P(P_WS)) { X free((char *) prog); X return NULL; X } X /* search from the beginning of the file to Curschar */ X for (p = Filemem; p != NULL; p = nextline(p)) { X s = p->linep->s; X X if (regexec(prog, s, TRUE)) { /* got a match */ X infile.linep = p->linep; X infile.index = (int) (prog->startp[0] - s); X free((char *) prog); X return (&infile); X } X if (p->linep == Curschar->linep) X break; X } X X free((char *) prog); X return (NULL); X} X Xstatic char *laststr = NULL; Xstatic int lastsdir; X Xstatic LPtr * Xssearch(dir, str) X int dir; /* FORWARD or BACKWARD */ X char *str; X{ X LPtr *pos; X X reg_ic = P(P_IC); /* tell the regexp routines how to search */ X X if (laststr != str) { X if (laststr != NULL) X free(laststr); X laststr = strsave(str); X } X lastsdir = dir; X X if (dir == BACKWARD) X pos = bcksearch(mapstring(str)); X else X pos = fwdsearch(mapstring(str)); X X /* X * This is kind of a kludge, but its needed to make 'beginning of word' X * searches land on the right place. X */ X if (pos != NULL && begword) { X if (pos->index != 0) X pos->index += 1; X } X return pos; X} X Xbool_t Xdosearch(dir, str) X int dir; X char *str; X{ X LPtr *p; X X S_CHECK_TOPCHAR_AND_BOTCHAR; X X if ((p = ssearch(dir, str)) == NULL) { X msg("Pattern not found"); X return (FALSE); X } else { X LPtr savep; X X /* if we're backing up, we make sure the line we're on */ X /* is on the screen. */ X setpcmark(); X *Curschar = savep = *p; X X return (TRUE); X } X} X Xvoid Xsearchagain(dir) X int dir; X{ X if (laststr == NULL) X beep(); X else X dosearch(dir, laststr); X X lastsdir = dir; X} X X#define OTHERDIR(x) (((x) == FORWARD) ? BACKWARD : FORWARD) X Xbool_t Xrepsearch(flag) X bool_t flag; X{ X int dir = lastsdir; X bool_t found; X X if (laststr == NULL) { X beep(); X return FALSE; X } X found = dosearch(flag ? OTHERDIR(lastsdir) : lastsdir, laststr); X X /* X * We have to save and restore 'lastsdir' because it gets munged by X * ssearch() and winds up saving the wrong direction from here if 'flag' X * is true. X */ X lastsdir = dir; X X return (found); X} X X/* X * regerror - called by regexp routines when errors are detected. X */ Xvoid Xregerror(s) X char *s; X{ X emsg(s); X} X X/* X * dosub(lp, up, cmd) X * X * Perform a substitution from line 'lp' to line 'up' using the X * command pointed to by 'cmd' which should be of the form: X * X * /pattern/substitution/g X * X * The trailing 'g' is optional and, if present, indicates that multiple X * substitutions should be performed on each line, if applicable. X * The usual escapes are supported as described in the regexp docs. X */ X Xvoid Xdosub(lp, up, cmd) X LPtr *lp, *up; X char *cmd; X{ X LINE *cp; X char *pat, *sub; X regexp *prog; X int nsubs; X bool_t do_all; /* do multiple substitutions per line */ X int n; X X /* X * If no range was given, do the current line. If only one line was X * given, just do that one. X */ X if (lp->linep == NULL) X *up = *lp = *Curschar; X else { X if (up->linep == NULL) X *up = *lp; X } X X pat = ++cmd; /* skip the initial '/' */ X X while (*cmd) { X if (cmd[0] == '/' && cmd[-1] != '\\') { X *cmd++ = NUL; X break; X } X cmd++; X } X X if (*pat == NUL) { X emsg("NULL pattern specified"); X return; X } X sub = cmd; X X do_all = FALSE; X X while (*cmd) { X if (cmd[0] == '/' && cmd[-1] != '\\') { X do_all = (cmd[1] == 'g'); X *cmd = NUL; X break; X } X cmd++; X } X X reg_ic = P(P_IC); /* set "ignore case" flag appropriately */ X X prog = regcomp(pat); X if (prog == NULL) { X emsg("Invalid search string"); X return; X } X nsubs = 0; X X ResetBuffers(); X n = RowNumber(lp); X X cp = lp->linep; X for (; cp != Fileend->linep && cp != NULL; cp = cp->next, n++) { X if (regexec(prog, cp->s, TRUE)) { /* a match on this line */ X char *ns, *sns, *p; X X /* X * Save the line that was last changed for the final cursor X * position (just like the real vi). X */ X Curschar->linep = cp; X X /* X * Get some space for a temporary buffer to do the substitution X * into. X */ X sns = ns = alloc(2048); X if (ns == NULL) X break; X X *sns = NUL; X X p = cp->s; X X do { X for (ns = sns; *ns; ns++); X /* X * copy up to the part that matched X */ X while (p < prog->startp[0]) X *ns++ = *p++; X X regsub(prog, sub, ns); X X /* X * continue searching after the match X */ X p = prog->endp[0]; X X } while (regexec(prog, p, FALSE) && do_all); X X for (ns = sns; *ns; ns++); X X /* X * copy the rest of the line, that didn't match X */ X while (*p) X *ns++ = *p++; X X *ns = NUL; X X AppendPositionToUndoUndobuff(0, n); X AppendPositionToUndobuff(0, n); X AppendToUndoUndobuff("c$"); X AppendToUndobuff("c$"); X AppendToUndoUndobuff(sns); X AppendToUndobuff(cp->s); X AppendToUndoUndobuff(ESC_STR); X AppendToUndobuff(ESC_STR); X X free(cp->s); /* free the original line */ X cp->s = strsave(sns); /* and save the modified str */ X cp->size = strlen(cp->s) + 1; X free(sns); /* free the temp buffer */ X nsubs++; X } X if (cp == up->linep) X break; X } X X if (nsubs) { X CHANGED; X S_NOT_VALID; X AppendPositionToUndoUndobuff(0, 1); X AppendPositionToUndobuff(0, 1); X beginline(TRUE); X if (nsubs >= P(P_RP)) X smsg("%d substitution%c", nsubs, (nsubs > 1) ? 's' : ' '); X } else X msg("No match"); X X free((char *) prog); X} X X/* X * doglob(cmd) X * X * Execute a global command of the form: X * X * g/pattern/X X * X * where 'x' is a command character, currently one of the following: X * X * d Delete all matching lines X * p Print all matching lines X * X * The command character (as well as the trailing slash) is optional, and X * is assumed to be 'p' if missing. X */ X Xvoid Xdoglob(lp, up, cmd) X LPtr *lp, *up; X char *cmd; X{ X LINE *cp; X X char *pat; X regexp *prog; X int ndone; X char cmdchar = NUL; /* what to do with matching lines */ X int nu; X int nuu = 0; X X /* X * If no range was given, do every line. If only one line was given, just X * do that one. X */ X if (lp->linep == NULL) { X *lp = *Filemem; X *up = *Fileend; X } else { X if (up->linep == NULL) X *up = *lp; X } X X pat = ++cmd; /* skip the initial '/' */ X X while (*cmd) { X if (cmd[0] == '/' && cmd[-1] != '\\') { X cmdchar = cmd[1]; X *cmd = NUL; X break; X } X cmd++; X } X if (cmdchar == NUL) X cmdchar = 'p'; X X reg_ic = P(P_IC); /* set "ignore case" flag appropriately */ X X if (cmdchar != 'd' && cmdchar != 'p') { X emsg("Invalid command character"); X return; X } X prog = regcomp(pat); X if (prog == NULL) { X emsg("Invalid search string"); X return; X } X msg(""); X ndone = 0; X X nu = RowNumber(lp); X if (cmdchar == 'd') { X ResetBuffers(); X nuu = nu; X } X cp = lp->linep; X for (; cp != Fileend->linep && cp != NULL; cp = cp->next, nu++) { X if (regexec(prog, cp->s, TRUE)) { /* a match on this line */ X Curschar->linep = cp; X Curschar->index = 0; X X switch (cmdchar) { X X case 'd': /* delete the line */ X AppendPositionToUndoUndobuff(0, nuu); X AppendToUndoUndobuff("dd"); X if (buf1line() && (ndone == 0)) { X AppendToUndobuff("a"); X } else if (buf1line()) { X AppendToUndobuff("j"); X AppendToUndobuff("I"); X } else if (cp->next == Fileend->linep) { X AppendPositionToUndobuff(0, nu); X AppendToUndobuff("o"); X } else { X AppendPositionToUndobuff(0, nu); X AppendToUndobuff("O"); X } X AppendToUndobuff(cp->s); X AppendToUndobuff(ESC_STR); X X delline(1); X break; X X case 'p': /* print the line */ X if (P(P_NU)) { X outstr(mkline(nu)); X } X outstr(T_CV); X outstr(format_line(cp->s, (int *) NULL)); X outstr(T_CI); X outstr("\r\n"); X break; X } X ndone++; X } else if (cmdchar == 'd') { X nuu++; X } X if (cp == up->linep) X break; X } X X if (ndone) { X switch (cmdchar) { X X case 'd': X S_NOT_VALID; X AppendPositionToUndobuff(0, 1); X if (ndone >= P(P_RP)) X smsg("%d fewer line%c", ndone, X (ndone > 1) ? 's' : ' '); X break; X X case 'p': X wait_return(); X break; X } X stuffReadbuff("^"); X } else X msg("No match"); X X free((char *) prog); X} X X/* X * Character Searches X */ X Xstatic char lastc = NUL; /* last character searched for */ Xstatic int lastcdir; /* last direction of character search */ Xstatic int lastctype; /* last type of search ("find" or "to") */ X X/* X * searchc(c, dir, type) X * X * Search for character 'c', in direction 'dir'. If type is 0, move to the X * position of the character, otherwise move to just before the char. X */ Xbool_t Xsearchc(c, dir, type) X char c; X int dir; X int type; X{ X LPtr save; X X save = *Curschar; /* save position in case we fail */ X lastc = c; X lastcdir = dir; X lastctype = type; X X /* X * On 'to' searches, skip one to start with so we can repeat searches in X * the same direction and have it work right. X */ X if (type) X (dir == FORWARD) ? oneright() : oneleft(); X X while ((dir == FORWARD) ? oneright() : oneleft()) { X if (gchar(Curschar) == c) { X if (type) X (dir == FORWARD) ? oneleft() : oneright(); X return TRUE; X } X } X *Curschar = save; X return FALSE; X} X Xbool_t Xcrepsearch(flag) X int flag; X{ X int dir = lastcdir; X int rval; X X if (lastc == NUL) X return FALSE; X X rval = searchc(lastc, flag ? OTHERDIR(lastcdir) : lastcdir, lastctype); X X lastcdir = dir; /* restore dir., since it may have changed */ X X return rval; X} X X/* X * "Other" Searches X */ X X/* X * showmatch - move the cursor to the matching paren or brace X */ XLPtr * Xshowmatch() X{ X static LPtr pos; X int (*move) (), inc(), dec(); X char initc = gchar(Curschar); /* initial char */ X char findc; /* terminating char */ X char c; X int count = 0; X X pos = *Curschar; /* set starting point */ X X switch (initc) { X X case '(': X findc = ')'; X move = inc; X break; X case ')': X findc = '('; X move = dec; X break; X case '{': X findc = '}'; X move = inc; X break; X case '}': X findc = '{'; X move = dec; X break; X case '[': X findc = ']'; X move = inc; X break; X case ']': X findc = '['; X move = dec; X break; X default: X return (LPtr *) NULL; X } X X while ((*move) (&pos) != -1) { /* until end of file */ X c = gchar(&pos); X if (c == initc) X count++; X else if (c == findc) { X if (count == 0) X return &pos; X count--; X } X } X return (LPtr *) NULL; /* never found it */ X} X X/* X * findfunc(dir) - Find the next function in direction 'dir' X * X * Return TRUE if a function was found. X */ Xbool_t Xfindfunc(dir) X int dir; X{ X LPtr *curr; X X S_CHECK_TOPCHAR_AND_BOTCHAR; X X curr = Curschar; X X do { X curr = (dir == FORWARD) ? nextline(curr) : prevline(curr); X X if (curr != NULL && curr->linep->s[0] == '{') { X setpcmark(); X *Curschar = *curr; X return TRUE; X } X } while (curr != NULL); X X return FALSE; X} X X/* X * The following routines do the word searches performed by the 'w', 'W', X * 'b', 'B', 'e', and 'E' commands. X */ X X/* X * To perform these searches, characters are placed into one of three X * classes, and transitions between classes determine word boundaries. X * X * The classes are: X * X * 0 - white space 1 - letters, digits, and underscore 2 - everything else X */ X Xstatic int stype; /* type of the word motion being performed */ X X#define C0(c) (((c) == ' ') || ((c) == '\t') || ((c) == NUL)) X#define C1(c) (isalpha(c) || isdigit(c) || ((c) == '_')) X X/* X * cls(c) - returns the class of character 'c' X * X * The 'type' of the current search modifies the classes of characters if a 'W', X * 'B', or 'E' motion is being done. In this case, chars. from class 2 are X * reported as class 1 since only white space boundaries are of interest. X */ Xstatic int Xcls(c) X char c; X{ X if (C0(c)) X return 0; X X if (C1(c)) X return 1; X X /* X * If stype is non-zero, report these as class 1. X */ X return (stype == 0) ? 2 : 1; X} X X X/* X * fwd_word(pos, type) - move forward one word X * X * Returns the resulting position, or NULL if EOF was reached. X */ XLPtr * Xfwd_word(p, type) X LPtr *p; X int type; X{ X static LPtr pos; X int sclass = cls(gchar(p)); /* starting class */ X X S_CHECK_TOPCHAR_AND_BOTCHAR; X X pos = *p; X X stype = type; X X /* X * We always move at least one character. X */ X if (inc(&pos) == -1) X return NULL; X X if (sclass != 0) { X while (cls(gchar(&pos)) == sclass) { X if (inc(&pos) == -1) X return NULL; X } X /* X * If we went from 1 -> 2 or 2 -> 1, return here. X */ X if (cls(gchar(&pos)) != 0) X return &pos; X } X /* We're in white space; go to next non-white */ X X while (cls(gchar(&pos)) == 0) { X /* X * We'll stop if we land on a blank line X */ X if (pos.index == 0 && pos.linep->s[0] == NUL) X break; X X if (inc(&pos) == -1) X return NULL; X } X X return &pos; X} X X/* X * bck_word(pos, type) - move backward one word X * X * Returns the resulting position, or NULL if top-of-file was reached. X */ XLPtr * Xbck_word(p, type) X LPtr *p; X int type; X{ X static LPtr pos; X int sclass = cls(gchar(p)); /* starting class */ X X S_CHECK_TOPCHAR_AND_BOTCHAR; X X pos = *p; X X stype = type; X X if (dec(&pos) == -1) X return NULL; X X /* X * If we're in the middle of a word, we just have to back up to the start X * of it. X */ X if (cls(gchar(&pos)) == sclass && sclass != 0) { X /* X * Move backward to start of the current word X */ X while (cls(gchar(&pos)) == sclass) { X if (dec(&pos) == -1) X return NULL; X } X inc(&pos); /* overshot - forward one */ X return &pos; X } X /* X * We were at the start of a word. Go back to the start of the prior X * word. X */ X X while (cls(gchar(&pos)) == 0) { /* skip any white space */ X /* X * We'll stop if we land on a blank line X */ X if (pos.index == 0 && pos.linep->s[0] == NUL) X return &pos; X X if (dec(&pos) == -1) X return NULL; X } X X sclass = cls(gchar(&pos)); X X /* X * Move backward to start of this word. X */ X while (cls(gchar(&pos)) == sclass) { X if (dec(&pos) == -1) X return NULL; X } X inc(&pos); /* overshot - forward one */ X X return &pos; X} X X/* X * end_word(pos, type) - move to the end of the word X * X * There is an apparent bug in the 'e' motion of the real vi. At least on the X * System V Release 3 version for the 80386. Unlike 'b' and 'w', the 'e' X * motion crosses blank lines. When the real vi crosses a blank line in an X * 'e' motion, the cursor is placed on the FIRST character of the next X * non-blank line. The 'E' command, however, works correctly. Since this X * appears to be a bug, I have not duplicated it here. X * X * Returns the resulting position, or NULL if EOF was reached. X */ XLPtr * Xend_word(p, type) X LPtr *p; X int type; X{ X static LPtr pos; X int sclass = cls(gchar(p)); /* starting class */ X X S_CHECK_TOPCHAR_AND_BOTCHAR; X X pos = *p; X X stype = type; X X if (inc(&pos) == -1) X return NULL; X X /* X * If we're in the middle of a word, we just have to move to the end of X * it. X */ X if (cls(gchar(&pos)) == sclass && sclass != 0) { X /* X * Move forward to end of the current word X */ X while (cls(gchar(&pos)) == sclass) { X if (inc(&pos) == -1) X return NULL; X } X dec(&pos); /* overshot - forward one */ X return &pos; X } X /* X * We were at the end of a word. Go to the end of the next word. X */ X X while (cls(gchar(&pos)) == 0) { /* skip any white space */ X if (inc(&pos) == -1) X return NULL; X } X X sclass = cls(gchar(&pos)); X X /* X * Move forward to end of this word. X */ X while (cls(gchar(&pos)) == sclass) { X if (inc(&pos) == -1) X return NULL; X } X dec(&pos); /* overshot - forward one */ X X return &pos; X} SHAR_EOF echo "End of archive 5 (of 6)" # if you want to concatenate archives, remove anything after this line exit