[comp.os.minix] s2asm --- .s to .asm conversion

cechew@bruce.OZ (Earl Chew) (11/14/89)

This posting contains a uuencoded compressed (12 bits) shar file (I did it this
way):

	compress -b12 s2asm.shar
	uuencode s2asm.shar.Z < s2asm.shar.Z

There are some long lines there that I thought might be eaten so I did it this
way to try to make sure the posting gets through unmolested.

The basic item in this posting is a sed script that converts Minix .s file
to .asm files that can be assembled using either tasm or masm. This means that
those of you using TC or MSC can now use the .s files that are supplied for
Minix rather than converting them by hand.

I have succesfully used this for Norbert Schenkler's string library posting, my
hard disk boot program (soon to be posted) and Andrew Cagney has used it
successfully on an early test version of the next version of Minix.

The product is quite mature though every now and then (decreasingly severe)
problems crop up. The most recent problem was that spaces were being eaten
within the text of a .asciz directive. The most difficult problems have been
solved:

1. Literals (as in mov ax,#label)
2. Local labels (as in jmp 1f)

I am posting this now so that you can install it and play with it. Soon Andrew
Cagney will post mcc which provides a good user interface for this package
(did you hear that Andrew?) (you'll have to rough it until then). Hopefully all
the problems will have gone away by the time Minix 1.4b is posted.

Earl
-------------------------------------------------------------------------------
begin 600 s2asm.shar.Z
M'YV,(T*`>"$FC9L7<]`H&`&""IHT<T!`!!$&1,(R;-A0E#/FH9TR+D"`D%*F
MS9N/%-WDH?/0S1D08LJ8>2.G#`B6$]D8+,/B)IHR;D#4<0,GS)@U"R72@9G'
M8A@[!E^F66J0SAN*(,RD86,SC!LR-_/`B0I"1,*L6\N("-GPZLDR<N[(F6JS
M#!Z(=*(FU<IU3D\Z8FV:18.6*X@68]:*S/*F#H@Q7BFRF7/53)DR8'%&#!-Q
M#AVO9,+(`6L03IVE4,,D'9I0=$^:3,..=5GV+`^^:GN"/..";1(S/B>*[I@&
MY<0Q;]K`X4J')X@\C9/>V:IQSF6?-F=F?#.==ILR<^:$.=-U*<NZ7W4L3)!`
M1)&O(-X`OYAQ(_&/+D0D'?+&37/_<^@@$F<NB!'&4IRUX0)A9+PQAPR-T>'"
M&""T$<8:,J55X1MD8+0@"#6%0<9W%LF0H`L-CI&42`^>:&%0+<ZAH'5@T8AB
M&L`UYYD+$>E(QQP\)G6%'&'``0=FL8U11D=EW`&$&'+4H61\05%1ATU.G`1"
M##1L&8,.-=B@`PTY;)D##CDH`$405"#1`T$&Z?!"'7/(`:<;<M)IIY1B@+`#
M"';!0=-2:[:I`(XW@;=4"\"=0*"!=)QP6$4BD+!'#'V(`$((/92%F*9_GA>4
M`B(MB<95K<DAX!74@>#&&TN-P<8;8L0D!Z!W>486;B!P(8*C0$)Z@J\*8&1=
ML1VABH9H`A:!!QU$CI$7;;X"6^"!PVK*!0HQP###8\M&VYP<<W"1@@(TUO:"
M%UB\\(*F/E@K+`@\\'!"$4X0\<431GQA1!),%'&"`EBDVT)0C/:JDQA<Q#@C
MDCR`4$(,/(+@@\04)TCP9S(.E`87>G)AD*QU=-AK&QI-["?!-;5188(>@URG
MR&Z0;#(7*&.\,K[Z\NLOP$4<FJ.B6WI[F!LV@7$'A8C1*R^V8(3ZDQNDB@1H
MLA:%*V"UCV+KJU!$&84A6-.Q!()<_;TT1QIZE!&"`EHE!118\H'P=*1PIR%T
MHIX=UNB):$C:`J668JHIIYXFYB=VHY:*=:JKMOIJK+/6"A>N>.VJ(=<R+IAM
ML9.5@>RI63,+@K/0&C7M2YPK&/C7V\X``PQ==B2:ZG"5>VZZ9JW;[KL6`^NZ
MI/7>F^^^_?X;\,!8[,!>`@Z#T`3,2)0AXN5&I$7P#MLW]%!$/UU_*Z]PR'%2
M&AU&9&''<]1AY*!9P>:P"]MW#\6!'7'UD484PU!_\Z<CPU1`@`2\T"0/ZFE>
M][K5@BS9H04Q.%,.$@"%FA2E)O&[54VXPAF0=$]V+0A"'<X`00DF8`@A:@X9
M_D>P)#AA"$RH`A&*P!Z3=(@-"R)8]TC`!"KLD`E)\*$"`>@0F_`PB"\;@_E`
MT*$P3.9L4R&,3L;EQ(B@H`PO,8D=*(('%HS`#DZ\4@I"4D00E(]67'$91+K'
MD@-A!P1@9,.5'A.9F``JBI>KB&DPB!PW>,8K=.A)15S0G&>!@`UAB(E&8#/(
MT'RF>XA49$A89;9(&NLO/X%C&&U2M_,<DBY$TD@;Z+04.R)'.:=!$F>PTSWY
MF,$Z2S&#^5SF21=0H0A8H()%L/@=_T@D*)Z$C'7B`YQ!%G(IEESD^&;)QDP2
MX0A2>$(5H+#+,_22*L#,I#`Y64P0H.A`%4EF2)H0A"DT`8KU.:5IFM-,;KZR
M##\BYB$3:2PHFJTF<SB2M&YRE?.DX5:G(I%UK`D4"7EO(F<H#GC:>3;ST0:?
M=6!#/&=RJV]^9IZ*]`L(IC8E3VIG5MUY21^M(H>\]&<.;*P,33J:R;F<`0U+
M&>@UZ3?$/U&AG.><3GT:]$:7PC0XM#$(")(PPR`P84,=ZHD83O/&.>3!/V'`
M@T0B(D`S6*8F_ND>1VWB2:0AR2H66<X`<>*2B+@O)6#AC'7:(`;#G,=E5;UJ
M0=F0!YH2C(=42``YAQ#-!+P!#LA):ASJX$06N)(%!K(."_KH&8(E(`E&$`*]
M!NM$'SA6)'\-K$T2RQ/&TL&Q16#"%(*&A01@%K`<L@EE%VG5+7"V"XL]Z6=+
MRS/($HQG3=`A%HZ8U[WV-;.I9<%J#6M5Q'8PMGZ<[6.-,$,C@.`'/_@(N=+0
MG^?MX$\=T@K2P$+1F\"L/W2][%"+R@3QB@2RDN7!:GU@W3^]"@2K!4$/+J8&
M4F)%BZ(KK=6L!ER3<?8U5H7E8V1KWM.)M@CHI9<KV9N`Z[K*+0&&IWPOMC;E
M<*7`I]4L"+807Q1P-@6P)>8[8T5@_5HMM*/%<'Q0:S(.$U8C'N[@"EP)8@"/
M>,#)+7!MC2!><II3O+@,8FYIFR_;EA:R"4"!+;,`A2+@V#,I`$$0\@4"&<``
M#0W^TT0&F-V=@,7#`ZS!N4R,9"53@<E.]FR4ITR$*F/9P5M>BB,KLL$#*=0B
M>6`K"+@U9M-:#:\*9G$9?,`"];Z8T#Q8<*$YBVA7"OB9T9RF@#QK61.CF+1^
M/J\1DKSD)C^9#FNF<@S>K.6(C-4N,<USGU``@S[O5R2`3K2@$;W>0BN:!XRV
M=827\H5;YG+2LJUTI@V<8A/O-];]'72A:YUHJR(ZUSR@M(Z+S&-+4QNT!Q8O
MLF>][$/KV@S/[F"C=_UI8>_XMOD:\@Z/P(0G_.]/1ZA<%>D8%#LNZRM<`8L8
MFG)3<\*$J3X^)PIHX()6N^HR9``?1N!`QDRN%9!I&`-*`2@:KBZ+*CG*9#*G
MRL0,;7>C<'&.J+QYALII9"*>%`^).-,]%'G<.4O%N%(X/KF.:Q=)/ZD))H%"
M<I-S/.5A6/G$_^0"5,/%#7;=+;N?H-<@\)7I@#D2"\!(+L="MKG/C6[NJ.N&
M]MK<RQGT;L?`FP?Q)D$*U*1ZH:D^!V'O=^E",&H"J*Z#J.?7S[C%=K']?/:T
MNX8';'>[U2`K`Q5?O0C.I;IC*5@%(0!Q"',7C8HOO7A<4D$*3HB\JNP^^6L;
M^W2>QWNZ0>OYO&/AAS#<H1*:`(4=\M#U3%#"NT'`A#=`1B/)C$A-!OO/KL!D
M@'6S4$+'$)(B&$6*MG<B1C'"<0L9"4G]L4KW*A+7D/LRX,O'(0BN,#40D&#U
MU+0.>+"R\9B0A4Z8Z<D`RX!'.70/_9LQ8TV@TI@YT!4$Y$$:D528_=?<:H#Y
M!Q<',GX5@31W0"5=`1\6(@=(`4!M1!5+81=X`23;UWV>M''"(2TO=G]=]G%"
MQ4,PM'/=(X&>`1138@:()!41(2O64Q,UTD\7YWW@ATX:$8#[YWL&F'U)!P3M
M-@1&)5];\CP-=DC)AWOT5(-`(8`DI5LDP$-,T'1/EP`9P08$`P1`8`)3F$"F
M=U<\I`10V%?UI1PL,(6.%89PD`!6B(49@6Y$H&Z[Q00P](5,MX:EY0)%(`68
MAW57F!%>5P1R8#[_!QPUUX&8X5AVB(=.MH=LT(=_"!N(8@959!.LUF=-R`1/
M6`**Z%B*"(3^@P5;N%O@)X<)8(9C2(5'9@3Y@G@@D(DFMHF=THD)<&ZGF(AJ
M*%ZNN(H]:%2VF(M'U2D\^`0^>%0KL"6D1P1&E@"5Z(4\8(:$AHFUZ(FCQS/(
M\S,!LS<^`@*R0SM'DS1+<Q@48B^`<P)1PSA5XSBD`SF]\BOA^#5#411'@21E
M0QAH0QMKTS9O$S<,,3?R)#R>DS?62#0)<P(-\B`1,B&"0SB7DBF;TBDB\"F+
M,W)58RK*8CJL4A\U)RNT8BN8HRNTP2O5,I`0<AH&22S&(CH263JJ<CK/(BYD
M\9$.$I(2,@;9TBO<,CO::#OBDCOF@BY(TCOLXB[P(I`O69`R22_V(HT^HSP"
M0S`OH`()`)(1(A(M(!)])%U+T09ST`(#B2MEP"@T82'F<15AX`)125%@23`@
MX)3#UB%*PE:7<P(X4`-HJ0)S"0+W0P?Y4P;[LR4%-Y=^B05IJ5M$`!Y*E`9P
M8%)!43>XT0*>$24:B$\)=%EC&2%":%I%AP?YU0*:N9F<V9F>R9GL\9FB.9HM
M0#!\8%KATR%RP!ZGF0"G"7+BPYJF:5JL69M6LP*RB04K0)J\J9FXZ9JO!B(8
MD7R(Z9JSF2C/4INNZ6<&,1.Y^9HB\9NMN9N]29HK<)QSIIRM:9RZ69W6J9S<
MR0=6LT'$R76_Y)RM^9K'E)O4Z9V?*9V9)IVFN5].Q59OH!&?T59EL)S+R43@
MQ)[N*9KP^9ST"2UDD9]<P9_;R0<$TYX!RIF_Z:`/ZINZI5M&`!LF@4'-^95V
MUA^[9!--,`4M0`1/,`7R]P9G0"1M\!WD(IQR53,V\2(OIELJ\`(5>GKMH@)?
MAS1O-)E,E9J78Y9NA`()`3]F&64U>J--N:,6EQT<2@?\=T%+T4F9!*2W4C>1
M$:(C6J)<R2@:DJ0X2C`C0(@)H"]&T`14\`53D`1:0$-5A@/LL:3UR$T9!);\
M9Z5F)!I+4:,)(*:$.%13\`6XY*;[!0-X4`-!0`-$$*<Z&D?H\TEN@"&WLC9G
MX`8'4@<UX5ZP8G$'LGC/8S5"17UUH!PS5Z1WL!D1H:@@@*AI::-AB@5VEUT6
M`2U2(F=?0)[2DD@@L`>,"@(D:J*XVJ'`E$B&45!RT!1@F@"LD0:5BB15D0!R
M\`6.!D_.LZ33&I9X9I\G%Q2S(B(M8$,191/)NJS-2AK^`:U?(%,%5:TZJJZ^
M5&=Y@1)@U3;FPSVE)83C:3W5P4L%52'V]2H':$<BTB%@`:9]8*],J:-;*:10
MBB12*D^>A*=@&JLR,:N.::MFT`9T\`5H0`:WL@>.1:X>Z$M2F'#,Z@;.DP!+
MJA.1>CF4:JET@*G.@:B*2ACCZD<GZZSGBDB>\05%01[IRC9E\"=R*K3RQ+-+
M\;/BZJK*BK/E^DMTD`!N$*WRX;/C`1[LBA5*RW$U$`,R`!.M&K)..[)1.[72
M:@:W.IP2E[53*T_!BIA*41(1<;,OJ[-1V['1.J=9:Z6,:;1"I0(Q8`-]0K<Y
M:ZY1VP8&\06R=!E9B[A!L;@Q6A+"R7LN2!%F,"XG^A*$^[3/:B%XH+@U,;0J
MJZ.>FQ6A6R&2JY>7XU4$NV=&\+I&@`9(RK0B:[?0,P?IBD4I*Z>?<12,R:_^
M\2>CU#=V]+9(LKED"SUPD+9GL+OM"@>:)$=<=15VU*VMB[RVVQ%KT#YMX+P'
MQQL6,:KRY$0:<0<TD7"_5!A+*[9U:[@)8)C,Z[V&&;USA`)GE*)!!RC^<:PM
M("A5,;OL6[A0FP`2E[O-VZO7*D^:];M2P:UOX*W@:AC8Z[ZX^@4(*KJ\JZ=N
MJ[8M<,'IB[<]$0-"8+.T.[:V^Q9R@$AY\`5N,*I9B\(J["JCJI%367/H5["N
M>K"Z-:8O)SU!<`1),`0P,&Q68Z@P$`.]*GP1)\-N*0=*M1(V$0-ABP4\?',^
M#,1#@,3!"0)&/`.]"AJ[U$?Z!L537,4[(65J6@100,0B8:A6UJO6<20W.%0F
MT&8H.!YE_*=!(*B>"'E;;*C=TJMVL22G0:SK2\5Z_`5)@`,P@`,VP,9<C`>T
MTZM)X!_,Q\@X@`,OX,B/81IYW,-[C`1$(`5?$#"9AXTR`,>G4E)U*D\2ZZIF
MS*._2L2&"KN;-KIPM'4>VET^2A41`4%3K%L4.Q^TND]A(*VGP;$>NZL!_+0X
MF0#'K,1CL`4RT`6-.QY+W,)-/,5-V[[@(AK0K+@I.`=9>\=G$!'=%<=TW&;P
M1"$3_,VW,B!?,`:FX;WT7`<='!C<7+M@\<S'C+=<@;*X'-!G8#9U\\K-_''^
M_`5#<<-9NS;N7,+>7*0E%<[2M3;]D;47;9Y_1*K).BLNP1['?$S>.Z<0BVK5
M=$WINV\ZPLT@?08B_05S5M)&6S=SQL`J+50L/7X?G38Q+0;A0=-M(T]`;45_
M=!11YJY+(1(]'=+A;*QYD+7WJZ+Z"RUYT+]O4!4N[=/A;!5T(`;>"RLYIQL-
M/!5IH'Q'O0;]"RU;[=3'7)_D#,>J=I\=;,@68;3)NJ0\`P+\`@)3@`1/(`6Z
M9`2!?4X&B[`YRA0M;0)G<[X1P167RT\@PJPP]0.?;,5[['A2@`+W;'<ID&2<
MO4Z!80)&'`,IP"D&-Q`Z>GE5X&2(LM./+1-TT,%OT`(^M:>PG,A7P`2;W=F!
M\=DH$-JG,=I&+`.GW0.IO:2L[=K`8;ZC$=N72]NV3=FX?:,C,#)R9#(\X!D"
M]`8+4FG773/9;1.W,0;^@4-H`-[873+D35W?+:;KK=U.-0<(\1D2DM[6_:=0
M@`1I/`14L*9MF@!=F\JX;-)8RD00H=9M97MK<-EG[`1/D*:A/,JEC"])MM_]
M_=]L6@0A]`6B3,JF_-E+JDYIU*]@&LLV@8I!T`0T9%HS0.`K"Q0%31B*F1:6
M^ATO4!1FLP)2#*:ZQ<_P_$M+909;@.&CY=\`7@363#!`CI-"7@=F(`-%SM]'
MKN%MNN18T.3A$A^G,>1;$+@J8.1%@.0;CN4$TYBU2A'(O+%XFY;'?)ART"E$
M6LP(LN;*?"LJ$&41,N3VBN;[1`:*J[%WGI:`#N=R[N<8*^AMGN=/;@:(33`6
M(E0H(!IG,`8L0.EV,&9:3>EC8*].K@*8O@58#K*`&>0J0`9PS@+/LZ3^:\FW
M`E:_V@((7>JOI@+Y!"VJWJNMCKE@)4U4(.O6HYI3O,6)>^-EL`4JSN*PU:NE
MP52X8>S#'IP1PL)!=^S)KN2Y;JVGL4[J"^U@NL5QC#XI6^!E<$$#*!$F@,-H
M.<"):]Z!!`*]RA"P+9PB8KK)\4O<GJS3[N[9KJ/R#L41(1=3\1^2'2'YSK3-
M^1JG80;]KK[I4YB'21-SR[3E4Q7(W?!S4#8=(2`5[TL;*@=@:9[)>D/P5`;(
M[;TDWQQ<J;Z6B[EGI"3A01;?#C;>7!6.59^YCLLW_;8</=>L=6/)6I]?T%9K
MT!-"[TI9:[W?RB'A"A.S<A0@P-@)K--LT.`S_])/&;1MD_-%.]0V#4XX;>),
MN[%SRO7M6M-#\RQA[TL]+2):+[H%CO9$",%,;Q@Z#?#!C*--V0-\W_=^__>`
M'_B"/_B$/_AS^3PO#QX18>[?,2X3EY:%'_F2/_F2[^,X>MUFD%T)\`6]5@52
M(`3`R/GK'NBI!81/\`5"X$)!(`598*\C,#<XHELB@2B3+@>5S@-?RP?BR>D^
M,`-11NJOUO%T`!PH(`)T<K4"PD1#R51;T+]DT`598>Q;<)ETT`5<X`8BD`+V
M^FH2N!0H8-S;#P)](/MG\Q"&@0*:R>EC1I\:3QBU?P9VL`6<W@5;``-=\/OK
MOE_;9#<M<`("<@?F+XDJL`(K$.KSWV=^EO%3T1%[!NJV'__SC__WJO\=9#=P
M("D</Q?^T0,Q\"=08CUK8*_LH?\=9#=D("D"DO(VT0,Q\"=08CUK8*_L(1+9
M%081M10)Q!XB(?S$+P)"4.\9/Q4=(3&6+A&52A.8<?TBP`*@;OOQ/__:OW@B
M,?[W"B76LP:('9S9%081M10Z@,L6@B'=7NT3[UBH#BT]4.S5_B>W'N?3;NSV
MF@!W8/Z2".JV'__S'_6,#>JV'__SSRDGX`(G@/_&=NIPO@+#V"F@;OOQ/__V
MFFFV#N<K,(R=`NJV'__SOP(K8*\),/ZEM:0HEW,)B"O_@='`!(/98>/5;MG)
M2ON@;OOQ/_]\?P(N<`+X;VQW8/Z2".JV'__SCZ2H#BTK,(R=`NJV'__SOP(K
M8*^9=NJ&#@/VF@#C7UHE*1*DGFFG;N@P8*^9UIB000<H@.JXOA:#G/WVF@#C
M7UJV;N@P8*_0`RV000=$FNIK$2'9'_XBT0>JK;\UTOYYOU_6>B1!P=A*9#TJ
MCQL3G_\20?PHT)P]\%=`@0+%7NTL</I20*).P`19D`)1Q@,&!_S!*?S$+P+-
M'DL:4@(147,S,11D</TBP`+%7NW:G__[U?W?K_WY+_XWNE]+2AZQ]$_$^_0-
M#L9,`O5B;-8G%795J<M!,?.S3_PHT.[^T0,A0@8HD/`&,>0L(.9DWJ8I<-QB
M3N9MBO^E)?S$+P(A`A8E,,8Z8O2G$E'Z9A,E`!93F4B#<OTBP`+M[A\L(.9D
MWJ;:[UC=__W:G__BG_\20?R%#BTMX`-L8+*5RBE)$*B#BO^E)?S$+P(U5Q&.
M"A:7F1T:,I6>\5?7G_WVF@#=__W:G__BG_\20?R%#BTMX`-F6[6XVG:FS<RE
M)?S$+P)4\`97\2)-P?,G=1BS^E?7G_WVF@#=__W:G__BG_^J_:'*/P:C6E#"
M&G:!@D@P:YY4>AS](4!P._.S3_R%#BTMX`-F6[6X.@<\8-K,7%K"3_SN@0>J
M<W_]81,\[Z%TX3*[5P>]!Q93"1EN<`)):SXP7R[8K_V.U?W?K_WY+_[Y+Q'$
M7^C0T@(^`+\U<0;X7UK"3_PB<`6BX09D,953G;]0;499[4LUYT;T^@;7G_WA
M+Q+C_ZK[M:3-'DL:,A%O4/0KQG,&SU3VZR!KTU9-D3[0\@9-08*KH[X`3.L2
M0?PH$"%FT`-*9#UT@`+3;NPL$*AG5P1!0`1\$*A)<`52$$1%D`)1Q@,&1^H)
M(/S$+P*0X08U]U<\9_!,50+E@OV&E<S&KOV.U?W?K_WY+_Y*J@*43_AV&4U#
M4`138*)**5^47_FNFO^JC7\2AJO9*@;W>0*+[R!F[:%"I?01?,CTF6<B(>=`
M_K^-O@6%#BTMX`,5?,$K,`/07R];(@/ASR)Y!@(K(.=`_K^-O@6%#BTMX`,5
M?,$K4,U&"0(T$/XLDF<@L`)R#N3_V^A;4.C0T@(^4,$7S./07R\@@`/ASR)Y
M!@(K(.=`_K^-O@6%#BTMX`,5?,%F3NO9.O15#X3U.1!V2>5C;N5%$/XLDF=G
M"QR=4I\28Y=4/N967@2(O5]+2AZE]/0-'H_"^?3"FJUB<)_1+A(\1>K0&NPH
MD/`&,>0RP`)B3N9MJOWY+_[EKR%$FF=#7_6:N9!<K/WD+Q)+2AZIIJUH14=L
M,`81=>YS.O'YOTMC`19`:!!#+N5';U4\#OWB:1!#+N5';U4K8/_A+Q)D;[2'
MGF<K\+7#:*AF$&6,[0>&ZNCY/_>`;M)`B`(O'64H4.C0T@(^8+95J[2_O"6'
ML6>%#BTMX`-(:[5`.Z>HG0)]QAXZ*N9DWJ8@,(R%#BTMX`-(:[5`J[?Y+Q'$
MCP*`;M*=8KUO?Q@W\?91%C&MEO]6`^@F_8J(O5]+:D$.8M:[_*6NJO^S,DPH
MT)S:G__GV0-_!10H4.S5S@*G+P4DZ@1,D`7:G_^_-,_^T0,A0@8HD/`&,>0R
MP`)B3N9MJOWD+Q)+:B$80A%D^:/!?CDS+\]PW@(^$,W8/,WV#X3DA,4P$/[R
M#.<MX`/1C,W3'`/0WRGDA,4Q$/[R#.<MX`/';,X1836=$NY@8=E[/%K4)"`P
M$/[R#.<MX`/'?,_!V2E[O,B-;`/A+\]PW@(^\,\>&]!6TRD3#N+X$O[R#.<M
MX`-OG6<1L5^O&/[R#.<MX`/'W-#I(A*O&/[R#.<MX`/'O-$>"H2_&O[R#.<M
MX`/'/&>OUBF`KK?YK^9PW@(^,-(HO5^=0O9"&_[R#.<MX`/'7-3!*>>%#BTM
MX`.."[J742\T$&536>C0T@(^D$_QF_]J#N<MX`/'#-7[U2F%#BTMX`/P6Q/-
MF_]J#N<MX`,C#2M]LE^'7NZ/:MDP``("\N;0T@(^,-*H%F7#^.;0T@(^<,Q%
M#0+7>:_A#.<MX`/'/&<@,(R%#BTMX`/Y%+_D/_O$+_Q1)OP;B@+:3_XBL:0"
MK_)1&;'!?CDS/_O$CP+[[DN=(O#-@0(1PO!JGNIH_.$5[@0I$&6(,^$@CB_X
M3^M68P;";P9SKII.7!9#X!4U)_`J;Z5_4@+F6H+U7C<E0`;7+P(LH&+[[A\]
M,>$@CB_:G_]6T_W?K_WY+_[D+Q(C_E=-$96>A$]3FG'9\:6NNE]W8/Z2B`+M
M[DN=$B)D@`()S^5?#>5&+[3R@0)[#N4ID`)1=C$&!_RO1OLHL.^^U"D"WQPH
M$"$,S^5?#>7JYP;S[!\I$&6(T^[^@?^E90;";P9SKII.7!9^"(@#!@=YH#E<
M\2<E8*XE6.]U4P)D</TBP`*+M^_^H7YN,,_^H?V.U?W?K_WY;S7C3^M68[UO
M?QB=TN[!F__B3_ZS3_S6^_8+R<7X3^M68P;";P9SKII.7!9^"(@2PP9CW-*0
M/:72=?TBT!/6^_;:G_]6T_W?K_WY+_[D3Y6S,DPH$"%FH/WY_QBS,DPHT)S:
MG_\20?PI7P91-A0LV^`H4.S5KOWY+Q'$+_Q1)G]580;%;S5:V1]=>?W9'_ZE
M<A=T,(GV.OZO2C#"OZ%[-F;`+W]50?PB</W7'^M6J@/7G_WA+_S$KRE;+!)M
M6S=*&R`B40(T@`>$834H4`(T`!9LF0+7+P(LX%B%#BTMX`-F6[5*JU&%#BTM
MX`-F6[5*.P?:O^["3_R:(A+S+E1(FZ?DD?PE0`-X0!A6@P(E0`-@P98I</TB
MP`*.5>C0T@(^@+16"[1EST0^"RTMX`-(:[5`.Z?:O^["3_R:8C6.&Q*0B[HN
M`[AB(A(E0`-X0!A6@P(E0`-@P98I</TBP`*.5>C0T@(^X+B@>QD]4>C0T@(^
MX+B@>QG:O^["3_R:LL56D]9]VS;)7P(T@`>$834H4`(T`!9LF0+7+P(LX%B%
M#BTMX`/A8<`]4>C0T@(^$!X&K/WK+OS$KRE6D]987167$T?)7P(T@`>$834H
M4`(T`!9LF0+7+P(LX%B%#BTMX`/YQ+P]4>C0T@(^D$_,J_WK+OS$KRF92]50
MC=55D?PE0`-X0!A6@P(E0`-@P98I</TBP`*.5>C0T@(^`+\U<08]4>C0T@(^
M`+\U<0;:O^["3_R:HO^IM?:HX43)7P(T@`>$834H4`(T`!9LF0+7+P(LX%B%
M#BTMX`,%/%`]4>C0T@(^4,`#I?WD+_S$+P+7?_V^#NSBHP/7G_WA+_S$KRE;
MO,5(A1')7P(V4"[8SP*.]>;0T@(^<,SF'!&6+0)34.Y)4,>:(B`BP!]MD`1U
MG/WA+_S$KRE;O%_'U+=M(R`E8`-L@`>$(1(H4`(VP`9@P98I</TBP`*.]>;0
MT@(^,-*H)D@^"RTMX`,CC6K:O^["3_R:LL7[==-S*B`E8`-L@`>$(1(H4`(V
MP`9@P98I</TBP`*.]>;0T@(^<,QS)D@^"RTMX`/'/&?:O^["3_R:LL6O5M1]
MVS8"4@(VP`9X0!@B@0(E8`-L`!9LF0+7+P(LX%AO#BTMX`/'7-2"Y+/0T@(^
M<,Q%K?WK+OS$KRE;7"K[>]6[+B`E8`-L@`>$(1(H4`(VP`9@P98I</TBP`*.
M]>;0T@(^<,Q0+4@^"RTMX`/'#-7:O^["3_R:LL56X]5.!-L"4@(VP`9X0!@B
M@0(E8`-L`!9LF0+7?_TBP`*.]>;0T@(^,-*P(@:"Y+/0T@(^,-*P(@;:3S#C
MCY3)`S3_V#?=,CM=<C#<R#3?*)0$*9(R.8ZB4HY7<XY:DXY"29`B*9/L&#;O
M2#91U%!I<]?VZ(_Y"!]U(Y0$*9(RZ8^(<HT!:2$8@AL'61:%HY"(TY"*(S4\
M%Y&/HS7;)SFP\AB5HY$DN#HL7RT6@B&X\3DE.3H3F9*HPY+4\BL6@B&X,9/;
M8@,Y\"TXB3ODLI.\0]\_"3SQ8B$8@AO$<Y3'DY1`PSP,,3T=L]'](:8XE0"=
MLCXN\P(?$S+Q;1,O@#)BVA`PL]']03`XE0"=PC$N\P(?$S+Q;1,O@#)B2C#D
MJP/0@QF7:1-0*9*#3#`&\4<9H0/03(<$_%=-`3B]$C+Q?7?(`0=-84,>0A@R
M(P<T8S-WAQQPT!3SDRY<L#".A1QPT!0V,LB]$C(%036EA1QPT!10*9*#W"LA
M4Q!44UK(`0=-T35+(3-RP`4%03543#!0*9*#K`-/N?PQZ5AXR31),`8ZP`5X
M23,V8Q,MP`1CH`-<@)=<L##*3Y`BJ2)4?.:8<9EEH`/0@QD3XEAXR31),`8Z
MP`5X23,V8Q,MP`1CH`-<@)=<L#"[1`83(J9G;B*=DR(Z`#TFTCDOXEA3ZTJ'
M\2(EXB*1(9[(H1$MT"<^,#\I(J8;HRA`DB`ZD``^`B03!SU(<C!^HS!IP##S
MDRX\X"-`$A$^X"-`HC%4O#&*0I9BH`8ZD``^$B2E93`(`QQ<L#`-8R*=DRX\
MX",5XP,^X@(:4UHD@`(X%64O\#$A$]\V\0(Y<XVN3S`LZ!4)E`!:R7PJ0)9B
MH`:.I97,IP*7>7=:R7P^`B0:4UI:R7P^X@(:@Y3)`S3_V#<VD`/?<C#<R#3?
M>`(6@B&X(8Y2`Q3E>#7GJ#7I>`(6@B&X,9/M*#;P&$4-E39W;8_^F(_P43<G
M8"$8@AL#$S>(<HT!:4,>$CB34A:%HY"(TY"*(S4\%Y&/HS7;)SFP\AB5HY$D
MN#HL7RTVY"&OHQ\E.3H3F9*HPY+4\BLVY"&OHRT#5P,W`,^X0RX[R3OT_9/`
M$R\VY"&!8Y3&TS/)`S3,8Z_CW@2II1&5;#,IKCTU99?X!!<HX;EI,$HN@X(2
M6!!3U!3[)IS6(0=001LI5^ZWH_))4,=HU3VG9!)!D01UO$M<(2WF"587:!`-
M#@?+8ATT9:\V]3TLSZ(8T12P9%;0FW+`NQ3&#B2S=Y=YN9?],WM%($!+44">
M<4"SQR4-=!(EA"849$$5%W8;9#W',D2]9GG0`[RE1,:FT59+?`)#\`0SQ#R]
M9GD),#<3]P5$P"9!`#W`NQ3.#1:FT59+?`)$P"9!P#Q?0`1L$@0),#<3A_I3
M,`70`[Q+X=Q@81IMM<0G(`13,`7,@_I3,`4),#<3IZ8W-01+`#W`&U.]V^`G
M,`4W-01+P#QJ>E-#L`0),#<3!VG2M,8IVAC0^P5$P"9!P`*H/P53P`)J>E-#
ML`0*@)3)`S3_V#<T4`,WL(T@H#1,\XTG8$,>$CCC*"KE>#7GJ#7I>`(VY"&O
MHRGM*#;P&$4-E39W;8_^F(_P43<G8$,>$CC^B"C7&)`A,B)E<)!E43@*B3@-
MJ3A2PW,1^3A:LWV2`RN/43D:28*KP_+5$B(C4@:?4Y*C,Y$IB3HL22V_$B(C
M4@8SN2U<4@-E@I.X0RX[R3OT_9/`$R\A,B)E0#Q'>3Q)"33,\SR5_$<9(:R>
M&OFZU00.,J499Q,&\4<9(:P#9C);EDTQ>B$98AA@#!V.47$40090D2Y@-2MO
MT(#G41-)=Y?$X1($(YJZQ1B.,;Q)BS^$82,4(DOW[DE-8!!I(%4"U)AI$'/F
M"58C$R+#%$S)\2)@0=`L03!@G')R[TF"<I\AD00;]11=,1E7$=^J9!$64A\Z
MWA&'H9E#!1,8D0:JZQ.="JO?DZ=X21C"P08A0@9-(53+810V(52>9!)]4Q-*
M<MY-(2@E"!8;[:%U0R-*=1HMM%%/81,U)UTXD@;.:E`.02?/T1@OTQ3:E1DQ
MV!]TZDDZSB0!WRJ0N!4T54:"<I]W/=1@?$HO`A8$;38ZSB2=<2H1I6^<M`9)
MQQ_*L15Z@06CJ5N,X1C#2V+*H2$V0B%@#)4B22%@11X1B)EC4,CZ28%E9"$8
MPBLZ98H'TAS*@:T\I1EA!QUUD'3\`0=YH!=8\)FZ-3\TTA,VY"&$`<:`XZ_$
M:Q/(,19?!8/L]^J4+F$"5!/20A-I`!XAP1AU0#"0$13<_E;I>P<7I[JW(D`U
M(2TTD0;C!QV.H1,8HE1,E03R)Q.7\P(+@U9,J2<O$-\>A*-E-,AC4,CZJ3[V
M5474:Q,&\4<9@1DAD03R)Q.7`U;<_E;I.R=U<B=)5P5KXQ($TYFZ]00P&ARF
M1E7]X1S0X1B0$13H]T;NN`97VW`3D?CAH<#]896:TQ=313`U%P:GD1QV1GQ\
M#:-2]A4U<8!#,!Y(TQ2"XAGJ,P:6_D9W<"J&D?CA08,PD5\&`15KHY^"!!_0
MX1@ZI1$"JY^2;7>165IM,`9,0R$^$B0X"L;DL130@:G>1"MJL&>P0991AALA
M<:&OGDEY02+F1QO0X1@ZI1'+(J]7,<@<`1'Y!1V8BA8ND3N165H&@S#`\0(+
M@Q`FTCGI$C$^4C$7XR,NH#&EM3XN\P(?$S+Q;1,OD#/7B-A!8!$0[_U=`VH<
M=T900;!*Q50#-!$U)UU-83Y+M2/>8SX'.$!A<`=AT!2K1!G]03"K!!V.01Y+
M`1V8NE&@$1$>&@1?41-W<`*=$;-6%1*,X1@6TA3+(J]784&(Q%(V41,O"O,;
M<Q7KXS+Q*'8*H@!(F3Q`\X]]PR4U4"8'PXU,\XTG$"(C4@;B*#5`48Y7<XY:
MDXXG$"(C4@8SV8YB`X]1U%!I<]?VZ(_Y"!]U<P(A,B)E,#!Q@RC7&)#SDR('
M61:%HY"(TY"*(S4\%Y&/HS7;)SFP\AB5HY$DN#HL7RWSDR*?4Y*C,Y$IB3HL
M22V_,C\I,I/;$@,S$+CPC#ODLI.\0]\_"3SQ,C\I0CQ'>3Q)"33,<Z,.@P(X
M$&5;O%]-8!!I(%45A*(JRJ)S("E'4`?H8Q-;_&H.@P(X,&8WZ@0K3EJO%CU3
M695PL11-8!!I(%5J51+Z^>I7$:*_2A'A41+ZZ7XX.@59`.%0L*93D/\L@B0'
MXS<#L3`(82*=DRX1@QL5<S&XX0(:@Z,S-`5\E0100`5)\`1.D/\L8B(=4Y5P
M$4]-8!!I(%5J51+Z^7_^(99UZD;M,Q5V35'Y3Y7),18L^Q+QZ,/^!AO]U@0-
M9Q,0)5%DH58EH9_CHSVT+A(6TA2FE!QCD6^2;8/GGJ53\*MUZD:TH@9+$DL:
M`AKY+Q(O8I@1-8!D$T69JZ*=(26$L4I`Y`1+$!^W`D1"D'1/T&12P"9)\`1.
MD/\L8B(=(QR[5",0;U!)<)5><;4]<A5R;)8;TC=4FE^OMGMUT'N9021^Q+!<
M%Q$Q=W"8H7!L`+WQ^$E4-!D]47*UG?\B82!/!,9/KWQF2(%E]!-L`+T302N?
M`78L83XC1!CH-[[YSR)PD0;C%WQ&83XK&'UA`':AVCEHP!9!,*L#J-)@%=_Y
M]6J:P?);)M[L;:YO5#[6PU9N%8-;YD=PP7_[EO\L8B*=0_Y64T80)5%DH58E
MH9_CHR&046\VH4YI`19T`A"046\VH4YI`19IW)S1H0!+01`($RJ<4X8,B!9N
M'IH!\8)-&C$OYL@(,Z>-"X8.>8`PDX9-F8\@?(PL>9)CFX,*8[9Q23$-ESIS
MY'`).(9-'3)E*+9AL]*D"YH["L),2"7(E"8@9N8!(28HSH8@`LZA4R:,PS<3
MFSAMX@+$D#=MX)0,>`8$1X9MQ)B44[3,G*4(T\R)6F<,&A!STJ2U2!)KFHEM
MQHQ!$2-%UKU7'09V,R9H&CH@[I0D&J8.';1AZ*1I@1?$F#!LV$P]4\9-&3FA
M@Z(F2@=-4#EEXM1)@]OA&+0SW9"90]`@EI@R%3\<4_>C4BQ&DC`I,J5TQ8L9
M-W;\V-`Z3CDO>/H$^L*E"S3/IQ0I`B((DRE/2B=>W/BY?>/W\^/?_QR*G(!<
M.11##"_$`,,+..2`W((@-!%0&G@P*.&$",607Q%.$/'%$T9\$=UT"AP&`E=;
M@1####'8\)!K((!Q!W,M,,?#"1J91\8;8YP`Q@XCVN:&`@J5X=<;@*$1AAPZ
M@,"%"#1JY]&-.2X)0AUNP!'&&&M@I5EMF<GQAD"`I:%'&2$H0)("(X#0VE<3
M-6DCCB>8F4:($Y&(60MMUKA=<"<\%`8((I"P1PQ]B`!""#T`&J.A/-;6&@A`
MJCEDD4<F><5F(+CQ!F8]O2%&5725@8=>HH%)DDE*,JFG1WPNJ4`9;##TZJ1S
M&(DD"$7@00=L8Y3:UI)N[AF&&R=(R05C,="`@VFV7LF5''-PD8("(`$ZQPM>
M8/'""X;Z$"RKP_;)PXP8:LBAA](5$2<6+E"!!&!.@K"L"`ZZ`:&A(N!;+X0@
M^/?&&;"UT<9K<_1YQ&Y`B5"0"U.\ZT003111T*I*MF#:EW:\AMF^$;Y51EQS
MC4AD$U,0\<04;LT!EURO+=PP"%-DX<034$R11'585`N11!19A-&JW(74W%XJ
MG=I21RZ_2P1U0TB1!!14)/&$$PLG`:]+!?WF1L9RT+$7QRFO'#*`1/YIQAMR
MS(39'+O1$0;+(Z%]<5IK@;GE7V(]!0+:!37U5%E4V`8";FRSX6O8'[-,E]%1
MA3%557.K99)#GX'`FFNP<>561"2;C/+9:8=6D*=J"(D9X\,Z%%P:<-3!1FP.
MW0T"'%X"'$8;>['M5\H@,)&$$TOL39?O0KB0-`@T%R%%$%%/7?752&.AEUO/
M@S3Q&/_!04=926`67!BL[54Y'*^!WD94;Y0(5H^WY;9;;R/"YL8<YH>6QI=[
MB>%9IF4T=!<6MF$#'#)SF;]8Y%FHF0,++,<&3R5P<PYIX&F(HH8ZI&4.@!-<
M``<X/4^Y+2!8J8V7ZG"&OUQE=!/Y$T/^8Y>](>9*7MJ+UC[H&H<$I&I22)E'
M_F(\+`0!,&[CRL#<@)G*B><G0:G-]!@WO2,"Q881<=3L<',[N-4F-(_)ROPT
MUATLB"$/.(3>^7KH`BA`H6^"(YSK#N<QD+VF+J89%E6"\ANZ36Y*DQG(PN8`
MAX(D0&<1P5//L`.T:HG$:"@I&DN.$CT7B$$.?IQ)1VK"A9ODI)).#,H+AM(<
MI.RQCUCP&U2D,D<\&F9^7/&*"QLTEK*<Q8YL09P;%\>2O4RO#7WY2V`&<Y@T
M=/$P89P/"!@S+>E!IEJ3J4Q6,*.9U+C%,Z`1S0158[G6O"8V;G&F%'&C&]Y@
MI8[!&4YQ/@+*!`@S1D,[WH>H4Y#K_,Q)05O8(]OYG?!09CQE*,]VT,.NEXE`
M/>QQ#WP4AH7Y$%,!Y=I0A]9)IQ'9!3,#4M:*@N(B&,GH6R[@TX[8]Z,@T<I6
M20(6T%IE*"I9"4M:*F"7OM26P(RI3&=*TYI6B5$^R:FA=N(91D'2IQ;\*5"#
M*M2A$B6"18&@43Z"%$*$A`8BU:I2(+B4,S7%J09^ZHVB(E4L&2=2>/+45;"2
M%5.="E)<Z8I7A^NJ>;YJJ&/%X`8XL$$,F'4D9Q%,6M3"B@BNE:UM=6NG#1$7
MN3*D4'1-9UTC2(!B.<(&RI5MDE20WQQ>]QE(8F$$!<'L915;A",190BVN<,"
MA2"'O@2E"'88UEY2UQ[AX.8.9@&?:\!XV<R"('#30R;V6(<9\LG!?.(3G&LJ
MH[(C3657JJ7L_>8G,K>`P#F7A6/EM,8US%Q&BY7[DQ@XD@;F,/)\C+LB,S$%
MN2M51GM=3-,7&S=)N;EMD@%A[_G:\`:@]%"S::("D9`[/\K*!HYF\-(8Q4>D
M[P[SO6UPS%4`DU(N2?%LJ7F#9L`TAC9$\$>UW>P?L;(S02IQ#BT`28AWJ[VA
MI0216,MPFNY@&]RL*(N"@0/:W$9$"`*F#G"@G5T8$MR@:"ITG(&FI)JZRH"T
M#C,6<<W_\'M;-.06*W,@,6;>8L$6BA<$>7A#'>C"M<!\:975FM[;4%4YM>V.
M"^.MC6W_Y#8Q<&\BU[U1"ZFZP-)&T<FYD_(P0^`8$6JYA`QV[.#*`(?7*1/-
M!%1S=-G\MK*4H:4<#LJU*DF'%R3@!6(,6DHRW>;,VC9P[2O<X9AX3R2N=I^9
M<?+NFDF4&88AOFU4G&WY**1>,N<W]FVR94H-%#CBLD2T>X,=TM#K![\APA,^
M@VV!0A)[B09_Q6'R%ZA0A%`BA"%G&"(=;/L%(C#OAPS.=FNV'=TO"&$**+OV
MH[5M6R(<00I/J`(4PLUN%8.`!+ZC0N.P]P;;DN`(3'C"OKWD;R4T8=XSX;>_
MF3`$)@R\W_;VE^T$]D:JVB7:"6A"^C"S/BF*2L<J6^XQ)5T&KJ$&!%F:BL>Z
M)O(>8?%(9<AL`AXZ9KW8QH84)T,:0D/-,)CA6>P#09(MLQ<JDB&#=I&-RC0F
M<IG72LN-!4%3HTXET=!&<$//(NT`E%[%6@S40@?AQ8CX:N:J0%,J$'I7=&XW
M)VN.CU>*N8:_WF*B@^#L;T@[BR\CZ9,&I2ITN$/_(O*GUU6%,\)9YEY.H`/$
M>EW7+IX>WO7N]K['?8Z!'[QS#0\K&H&`\7U*G<P3@)!A344KN^K+LS&<V`30
M_35VGWRJ^0X8OV->\(\J_-LZO_@>A#[QCAH]0D@"K=X>B>-P]AH(4NL3N;?>
M8D%PYM[?;GLQATD@J()[94;_>A?#/%/[A4W=6NKW)3_>49'?B^S!.6Z9@QW"
M#4RV6\B@\]6??.6KW\O4'>)SH$M1Y[C1*VF0,?H7!ADC<U7Q*,%&7""!<:['
M/NEW=V@W>]1W>4<R0L`G..`4!NZG@?CC/JVA3!UG&PR!."R'/VZ!&]RW>;M'
M%-,3@%^B%UBQ7EZP!5X``CK0!2K@@!8C1ZA76@+X92\H)#%8+6500&_T1:.7
M`#5X@SFX@S8(`CJ8`*"S.5JT%4"X>HGV%[IW>$O8A/<VA50H-SZ(2EFX7%NX
M-_O3A;`B<U<0&KNC9:?C7B08%!]'.%XV/_?E?N%W>1]V,;UV73!(<<(10D:"
M&5E6!Z;D@&D069?'8K"'95J6@LZG6*#$9$N@*7<0$2=@!EU!!UMF%WTR@D'1
M!@\2(2"QAYLE!:'18BX7$3@12R>0(PM$(R_@`BIPBR[@`IAF)/FC>9$Q1Z>Q
M8.MC-I\8BC*'`K?6&3P6:,T5!CD&<T1$383C-EU33/B5`&!W`FG0)RB@%1KC
M&%C(.GMA$EX12]-G><H47U+$%;K27%4A<^#8-0VABFD"!7"(!B:1,401`RX`
M`YX67450?R"`!*2"-GG@@&=1;$ZU*ZP#`B.0=4.W%R@@%9`#%":A.1^&C2W0
MD1[YD2`Y>E.`8S+6-7QA.&EPA:D7A!$QD:,'6L/"&H!A@+&T/MBF15)W;)+A
M=[8%`C;0`D_0*RT0`SF0(`DP!1910MY37[9F/RA8.201(6J0%B"P!6*`!UUP
M7PA!`T`IE$1IE$%`?]]47TE$)-2E,7OC6Z&!-N:7`$8`(5B!`DU%/F;@.M14
MA6?P!O6%@RW@&"?@`GUREM""AI7S!3="!U\P>F'Y1%&A%WD$`FI`&2IYAE\R
M>F^)!UBA`GED$FEW)&=0937V&P032RCP19JC/72Q%75@!F:`C8IUF5C!!$$@
M!$7`!%:)E3AY0!AD6S*0`RTP!80VE$69`PD@!9*VDDC6@E1!16NP%S?"(EPS
M%5TA!]0T!_MUB)LS%2X`@*8S@)68`-/SF=+(%2%$).551(*S%<>W2H4'0O>E
M6$R@G(_4%6L02X(Q,#K'<U,!?Q(V@U.A-<#F)0S(%KR)`[\9G%])G&>Q-6A9
M%H5YF%^`DS^H>BUG`@SD*7M1!F[#!K9%E`<*!\)IE`M:752!!U\0&&JRH<UU
MFRL0&%V0HJC1H;X)G"":H`F0!"D4=IQB)`(1%/6#?%K$G;V2.]>)10B6%4!Q
M<O0%%*/':FZA&(2&GA^C)LJF80EP!VCC$*@Y3#9@E7/0HFG0!2F0`)^1`%N`
MI7*@I;O"I2L@!E\:&"G0!;8U`S#0`D%`0B%*G$WP&C(I.Y416IZ'-FEP!@%Q
M<KCF?"#0FRV@!*Z3IPEP!6B3);&C4FO@,SB``RAAG0,#&'D0%\>V%V=#)8)F
M)!FS4F#B!K=C%Z/'CH(CJ(2*JD1AG5NF3"C`$$$!)=B8J+[)J&S@J+A!7Z6:
M=G*3)B*"IFI*%V(FEH)VJ*,7E;&D`BU``Z4)!WTF6<I5F=&EJ+SJJ([87]B$
M&Z*!7909143B3=O#F[O:J#9Z%G(0@'1`3?PU6;"S?/Y(`W^2%GAPJ096.4?Z
MH^^9`$1`;/Q3GO-'.5@G=@#W!$+@'B!@F'"``S.0`S#P!0"B`TY0!$&00WOG
M%ZNZ%Z88<F#"JJ4(!_F*J:#*$B&0LBG;H37PH8ZJ<1GC&_A#8YR",:/Y98?:
M7*YQ)$"TGE[!=E7:>CD[73PJDPY*)!$:7YP7*S;6%QP1%%,P;QH:HQJ679@'
M=*@Z,%HI`P:ZK3:ZIW+`&I+Q:!\S;G0E$+'$K-G:M>HZG`FPF%CA`F=@58BG
M.EY1BFN4DEDWMP[$M&^P!L-D-7-9!KD*`S/0`DW@.(X*MP[A`FAS!@LT37.2
MK5P9!+2SN/3W7!PQ!FF0DJS%2)RK!QUZN)8K!XYZF5,R0&G"6FEWJ%H9`S)@
MIY>[KK:!)7%#%\S6&8;S7.ZX-NLV;@MT(VH8>#86$'?PKT7@!CQ:&8V[)AT:
M`[)KNNM*10'R'/=(16X4D&D2!%*Z?*^QG[Q1(D.W0//8O9)T/CI61:BRL7_!
M;""T9$&';=JVFU@P5WM0$'@P,;>8BSR`;3I`!3[P`OA;$#91$+_3<%6P-#IT
M'EQ0$$XQ!540,0DP!L0Q;=5&!2P@3NX&;_)6$&(``C<R=`71!_=QO0!B&EN&
M&S4FPM'5`R[\PC`<PR^LO;J&PNUJMEDW/5M'1%C!6E*4LV8P&\$U0H!6.1Y4
M=@0:75+D&N\X=$CG?2X6>$0R;G(P%3(&('NQP^\J=A9*!UK,PFGRQ6)7027"
M$,+18V''(G+HH&+,(L0';)YA2U'T-JO5KEHF'+;U8.$[96$+FN2F`U[\'],(
M0OKK!<<2A3HH+13!!3%P:85L:0*<,R_``I-,$55:$#K0QG('2M8+`D>@H4''
MQ$A&R"TLPZ8\P_8&=J*<QG9WA.BW-V)`0U@18&@1=$:V/XQ#AT&Q?[47=UH)
M=KRL?7;G%T(BJ2M1?&4A!&4`.DF$9UGTG&7``K9%S+8+B:_\A],C1=$I=!PQ
MRJZQ0*PE(M8YO$?&/K8E8^KI1CVD`ZRQQ:[Q'/D;72*2=7-@@(:H@&\P0-N%
M)>TT+CPP=#J`BSXPT)AVOP"DO_X,T`)-T)$<SWR%BPD-0CIP++@H+0/M`[A(
M`B_`R)'\P6O2SBQ,PE@0SP5!`E01;GX1DW)7$!B&R1^MH2S\:;S2S$&1=1W'
M*['4&F.67B!PRC[]TS(,S_V,7)41P"!@T`Z-+2^P`Y$,2GS%U!T-PE_2/T-B
M(5@@TO&<)-`\5E:-&5M=U9WL'X0FH#O&RK8%U#!,PV`W!BELMK?LS:T\)#V\
M6G.C;2L!*_R';+$4?-%U%71!M,4<=/%ZK1&Q@#OV9D&7=:ZF%>`WS62Y0(8-
MLFWQ+*:(JB2B)IZE<HD'KEO&7$8<RV47RJ)";FGBQ#7,-FXJ&J#X=GW!@"/Q
M.FTQ/3TQG7L3$5FU/4W61'L!B2JHQ(+S-L*F="N4?Y2H)NHI%S97CY@LU2SL
MU<=&RFDR!_4Y0!^C/5/ADMI2@TI"!SK(![B(:1\,TJ2,+5NPW3JHT0D1WC`]
MWMJ-9CHX`AG]`NKMSH@ZCM2]S4HD$$G"?D2T%Q8J*JXMS/_#5X?L!7R0R"G@
MW2J@T1P]:X5V&1EASR<9KA/*DJPLQSD9=<+<3DTH`CN@@TQ]U`6!!`,LR5S@
M!KBX`Q2M`M*BT1'M&A,=`Q?=T/J[`]\=R2*=)L@U?KV\?9)<WNZ]X-MB6^8(
MM#TN=WP%Y-R=BY$<W;9W@7?,?]Q\>(O7>(5<X-O]A-*BY#JH`UR>BXRL`TU^
MY*OU<V_TQIAQ`L8ZBBU)R@2.`E$8Y%MNWE^^T7,UYABIH>K80E`NJINW=CFM
M&P]T`NZ30.ORYE'8`PA>WCK8`W7.R#T0R<L-S?A7$,Z]LTO7-24<)H-!1S8[
MF/ASUF@=PS3,$8"!%D%!BB5X&A%!JJG.-:^C%F!RASO6<HXR%0M6>'K)0:BT
M=K:U/GR[742!&X46=]J&=)\'F-F4E_]1&^>#(VQ-.%(7B5^B&L^A`Q\G0%:=
M)H(Y96YPW8`.)H:'*G]Y`I[WH)N2F))LR'`>!BV@!T'0`EI0ISGP!0C.!2YP
MR.X.[_).[U^`[P@NYHQLF.G.!3(@YI:N)GA0:'!@U9G5[2QX>&[1O>IIDH7)
M1^K.5U%;X/L>[_/>`O7>!=+R`B<*!_].()TL(G*TN9VK!QP%&-,]:"5BZHK]
M)31$U^,H$+-&),]Y`LPT+$5DED5K&>1VBRR_!6+2!>"M)H6X\->>[;MN6T@@
M*F.GGJ'YZ7G87.=[NVJCOS"P!7B`!2(/Y_0>[T;@[F;0!5M0]BUP]GB"X"\`
M`XR,!I&,&5"?SYU,[(9VJYOB>?%5<M_;(['4?V^DQ\4WY;"B`Q6^>E<.YS>H
M@U5IR/DN`O?.BP,/H76O\(46]<:1)B.*EDY;@G/0J6+PJ<VU*:YH/L,TN.#'
M(O&5\V<P!\4T:8[O\?ON[R*?`AM?^_)^^R!O[R,_\!AO\)%,^S9H^^^.^](2
MM0P>`R7_!9E_]YP<7<99[,ID>I^W!7VRBV5Q`EW0)[*#@5HJC32BOURP!2^`
M`B]0I9.F]"FP_GE/:'N?G::1EM=460/^`B:`:4&0(9:LOR6`:4WP!$3P_Y(\
M+IC6,`X'_Y),T#"#!#D$_Y)LU$>@;_`OR3R`:4R@;_`OR8B":1?[_Y+LPIA6
M!%'P_Y(<`I@V,_H&_YU?39CQ'VQ"@7N>@N)?UV%0_C]NWBK``G5.R>S_`EQ>
MY_]O'-C>]*!D]TT__6G"V7+`7+1\/K,HQ,TEWJZQ+DE]XOW[:.`:P)F/;>!:
MXK;U2KL<B2(B1?3<5*[C$)#C8I&=BIC<&\_]SON1)E,0+T(J&@1X**(^ZJB,
M+2Y`U&6`WDB-T$1=!@%<_$K-`T1=!@%<XA]<3?0]PIT,=O)KMI&=1Z(^ZJ9,
MPS#9HSH[VO36?AF&+?C>NTN/;2G=HQR.[V00&F&P]-B6TCW*X?CNIM=RTMB6
MTCW*X?@^4TN/;2G=HQR.[VN"WA^,;2G=H\_QP9J";2G=H]>.;2G=H[;UEO92
M*T&G8\.F9;GSNT14XB_0OX\&R`%LT`6,!18<2C-WQB/<S_Y+!@%LT`6,!=WV
M;3-WQB/<S_XK!@%LT`6,!>:&;C-WQB-<XK8E(E24&M*9@8_2;#:G)K%RG.OI
M&K`EO^V'!2;MT<)A-!R.[VNR]&MB-![,/W>`;2XM'$93TB(N/0V,!>52$'$P
MPE?N`FNBT>52_-B"[S/U`N7BR%@`2G&PZ16/&:X!6_+;?L:A`ZYQ!]C&X?C>
MNR^`U`CMORX0P/W[:(`<P`3<P%A@P:&T8>)&1"/,X?A.!J$1!B^`U`CMORX0
MP/W[:#I`!@%,P`V,!=WV;1LF;D0TPAR.[VYZ+4B-T/[K`@'<OX^F`V(0P`3<
MP%A@;NBV8>)&1"-<XAY<3?1][9J";2G=HPFO*=B6TCVZZ:`5V%58Z"0BZJ/N
MPC2,HU98Z)JS1%$>N4._3.M<Z"22\(5.(HV_!5^`_'J@]E^`_'I`[PC>`RL>
M_(WL/@E`_`FOR9N>*\\"J^MO5:CQ`JV#W,PQ^IY*%$#1$W65?Z(^ZJ,^ZCU`
MPT%@V[KR&K#*J9[J@LXI)*_3&\@^^I[J@LXI)*\#/Y43CXLV13C2$*&8%1,A
M>"?@8M&NPN]Z>G>61*--;\"[-^BG&;(BS]9%UV00&BI$^L>FE>OS&UM6@NO3
M.LA-P:V?ZG7BS$:28ZVQ9!R.[Z/]&FZP]*-]!G+!X?@>[&RP]*-]!G)QY=NY
MS&+W`E!0!4+@.T/@R%C06X),WQ[,]$"A*V<@%ZTC!BZM*V<@%\^!+?@>[$11
MT"7^`OW[:%Y.!=QMU$A]Y7)+MTJ"`A7]_O\6<"!PL1G+`CS`R`'LP5,$("%=
MX@0NMW2K)"A0T>__;P$'`D*0!=3&`CS`R`'LP5,$("']'`3N`J/]&A'Q`A<L
M!4[@R"/=S_Z[!53`W4:-U/JKT1:+L5)0_).L[^_N\<K__A:+L5*P0!Q=I1^L
MR2-<XM>BT3H@!%E`;<4_R8>,_'J@_.^O`T*0!=2V0!Q=I1^LR4_?]'1P!G+1
M.F*0\&LRVF<@%ZTC!IU,!,NLNT'O4.\HO^U7RJ-^RC0\!:@.B$'AI)#S,9<1
M(&5!!,NLNT$?="[0N_3FUA,A>"?0VZL;C2K\KE-!53B)_?([;F6!`H!?Q8(_
MZ[$RS&1)%4]+!L44SR_0OX_VOT9MT-?2OX_VOP'<OX\&R`%,P`V,!18<2ALF
M;D0TPB6.[<)!![K";`F_)G2@*\RVZ:1%GX@?*Z+^TS3\0UDG.VSH@OGC)5D2
M$60S(EAZX<B.YJP\=C24Q#J.=<KIP^E)A(FWV/8")C],ECV4Y$ZH]D[8Y?K?
MP-J2\'GYKBWHP4Q/!DN+R7GYKBTHU-K2OX_FY60@!EU@U$C=^%&HY2D@\(V\
MM`E@FOE4XB+]`OW[:%Y.!U30!4:-U(V_]B"O]O0>\"^`;PV7`#S`R`%<XEA=
M$&>T[A7M!D.>W8PNY"<MWN]L'-@N'$N;\&NRM)LNOV8;W.U*;(@ZZJC,9+@E
M0V1YS&5LSV@LOV;[95*$&L]BV35-*EIY78Y2V#A!@H,&BG)`KM/N8E\F118Q
M\XDWBT*,6-5$W\W5SJ+=Q-`->;(1Q6B`&[=Z&)ZHPISRM`0F=:EC$K9%J!ES
M9SZZQZR<12KTNS4F10RA-1$D=JQ>2M@/%C)G,:C?,IME,8N/AJ[1$%NUQ[-3
M5P/S+#)G,8N/AJ[1$+'$$%HS_@&CYY:%+3>Y!4(R'%TP!^C]P:Z.;1[,],/Q
M:)CLZM@V:Q(N1?)KME\F1;8!C?I[DQ2=[^_/`XP<P",^S;-13?3=7.TLVDT,
MW44"=0X!.6/0OX^&&V?@`_K[W?W[:.`:P"/NP=5$WYB,;>!J6\%<?3+4UD24
M68TXTTG"V7(0$;1\/M@&KG&4&IEUB=G$&9E.W/M7)M%EJUF1?%E4AEA(H=@:
MSR/0B#/-+('-V7)00Y-)H=@Z`J!$WONN]OL.^4N/;:AG6]<U/51EA8N/AM0,
MN%)D&]#87$#!N;W&ON&V-UQS!\WN8_WS1"5.^Q6=`B?.`Q0<P`E`!F*0`#`@
M`V6`!@G`(S=)P0V,!0UNXBA0T2EPXCQ@%P&<`&0@!@D``S)@`VB0`#QRDW;1
MP%C0X":.`A6=`B?.`\,1P`E`!F*0`(9;!FB0`#QRD\/1P%C0X":.`A6=`B?>
MOW,0P`E`!F*0`(9K`VB0`#QRDRK3P%C0X%AP1NM>T6XPY".]9IG.<9Y1SM&N
MPN3VP;WQW.\<75.]2E*T^"TWSL!*T^$V:(2Z%6<N8-,.C7E\G:GN&>5LVD8@
M8!!(]'$4$9!3SO%E_2>!R=B&>B6^NIE.!TEB&]!HPRI,VK.S/U(DOV9KI()#
MRS5&BM,.C8U?T2EPXL?"`[OH`\$O`PT>7:U3*T%G&]#87!Z7>*1(SIXQXLL&
M*WH>O[];8R([[="(T+L8P#2^:)G.<9Y1SM&NPJ0]._LC1?)KMD::GM8(I%+$
MPL9OR&YP[VYP+#RPBSX@+=]M\`T>79J(/J4J1?)KMI6SM,W%VT1?)%#G$/$H
MSQ.!YBD8VW2-&X2Z%86?5,'=KL26ZA'!$%I#!NU4E6\S!F2@]GB@CUU`R2>-
M;10L`WBL+54Y!D`Q!UV@0$N/;10L`WBL+54Y'%V0!I1\TMA&P3*`Q]I2E7,@
M!ET`!Y1\TMA&P3*`Q^O.`Q2=[RG@`_K^[AZ/X$KB^"P`]P:O)#&@`RC`!3/P
M_A[,],/Q:+;EZL[%$%K#?WU<;TF";10L`W@LR3Q`T?F>`CY0X"R`X"RPXL$O
M`RP0YBC`!3/P_A[,],/Q:$]_QH^6\&N";9M>_9\X1<L,(:(.U#1<_9\HVDWL
MYMA"[!I-!A\,`V8P`VB0`#Q"[)D?R`#"PGQ%[%M0!GK0!1I-!A\,`V8P`VB0
M`#Q"["XO-\2>3PD?R`#"PGQ%[&ZP!66@!UV@T63PP3!@!C*`!@G`(\3N!BXO
M-\3N&ID?R``2TYW?'DD9$:MLT[:=,1%1^J)J7*(^ZJ.>UO:&HT&7LTUT9Y[>
M:_(+O&J2,1'!ZE152JT!.LQ[ZLMD6TUT!C_6$`N$^J^A&27X,=?U)T(J&AG3
M0]CB`H#O!NB-U/WLOUM`!F+0!4:-U/K[W8#O!E$=R``2TB4^WR'=R400&BKT
MY!%V&HQ?RJ,>U*E<AU(GX4+J/33A/@.(&N-&I((M63^*AM/3%:/?0P3N2'F@
M.99&!F+@R.N.[\9*$0E`!G?@R.N.[PT$)I9&?XZ\[O@^)EX"6RL^\@E`!G>0
M`(P,PC@V3##P_E=.3I>WXB.?`&0@!@G`R"",8\/T`^]_Y:#;N121`&0@!HZ\
M[OC.\BZ_XB.?`&0@!@G`R`MT(`FOR9L.G#7;:Y=S_VCHJC=4RJ,.U&KMS#,!
M!\[I3;T"K]=9BC3QN/:?.<O50]?BN&&K)"A0T>^?`(^;``V.!;TER/2]Z?BH
M,CU"Q']Q&`L45M&L)K%RA&:P0&L"3*4\ZJ-^R@&)+8>Q])K,X6%UA&:P])K,
MX6&53R>MR1R^)H>Q])J\Z4\`!SDKF'DHZJ/NPC2<N`.4SX=*8/*E)MW$?..&
M034\$^S($8";S4[5&K(27:8I:6*"%?E\J`0V183V?57XPV_P&IS[9:1H__(S
M'#UD6TG0]#U,?WB8Q$P&DST:I%3_LWBXUT2R]>XS@*@Q;CUT+2APR,/1!3:1
M`N^_!8RL]/J+`L<B!EM`LKG__EO`R$JOORAP+&(`]G"0^USP[W`^'%U@$RGP
M_N?/R"M@\%R@])/^!@$!%/'LW`$!%"2]:-HD.&80?V.W*\<VF12*/ZJ(+=.T
M]/'JB9:%+5,)!TL?KYYH6=BB!A1QTO'JB9;ET<(1KYYH68`L69YH6>2][SJ8
MDDO/==#R:"E/1+`AOV9;01?43D"P]`$!@``"&[;%HV2`*M,T3%<Y^QN]!2LN
M+4K?X%A01)IL6SQ*!J@BI)A101>DOVI`$5,)!T]GDF-.S8!;A1)T<J!S!T?B
M$!5T09A<01?$ZARN!HB<=FL/\FI/[SIH!NC]YFJ`R"SN&(=,[VI/[PAN!AI-
M`@8'!0G``XSL`RS``P8?P/H[E7#P=%WS`E,Y0$_7-5$=R``2TUB@^,+!&P`"
M&XV/R"SN&`4.!`@.!"L^\@G`R%>:I;.SIBA@\%PP`^_?3N>_])JLORA0X''*
MXBGP_G#.R&*:^9I,P#R2!#PL!["J)G9,%U@T4^LSE0-TJ/\3!RG/P]#RNU=/
M1%Y"&Y+EB9:E^,+!&UQG6>E?T>A_TH$,("S\P:##O/^#R5P'+8_6^#88IBR>
M`BE9X$"`X$"PXL$_5V1@K+.SIBA@\%PP`^^?\`$!@%QG67PEN4KB^"R`X"RP
MXB.?`&0@!@D``SD0!G_!(Y+;P%B0`&1P!PG`R`V,!0E`!G>0`,2?\)I<R%.I
M%DKB^"R`X"RPXB.?`&0@!@D``UWQ%SPRE6K1P%B0`&1P!PG`R`V,!0E`!G>0
M`,2?\)I,P#R2!#PL!["J)G9,%T8J.#.U/ER7FK];8Q5T0041!T\O'/'JB9:E
MX^GI-K:[^"V'`JU3*[.3SX,&BG+@!L54R.":!AH-GN":^9K,X>"*WA\<R`#"
MPMABKNC]P8$,("R,+:U3*V:`WA\<R`#"PM@B8W!@!NC]P8$,("R,+5NQ!3K7
M!>C]P8$,("R,+3V!]&0P!EV`WA\<R`#"PMA286.`WA\<R`#"PMBBCW2`WA\<
MR`#"PMAR!Z]&!^C]P8$,("R,+6JP!5>2EWS$,GKPHDM?01?$ZAP>F59Y!F&@
M!P*4/F/PHDM?01?$ZARN!E8)!P*!&EV@22==01?$ZAP>F5MP!J@A!EV@22==
M01?$ZARN!C)&$2==01?$ZAS>0/E,$2<=R`#"PMC20/F\!66@!R^Z]($,("R,
M+0V4SVZP!66@!R^Z]($,("R,+6HP!GC@\DM?01?$ZITL1;3&N2>W^$V787P5
M$!H-GFZ0`*B1P7B0^9I<R'*HT0D@APE`!GC``JB1^9K,X2>\]($,("S,5_&U
MXB,/GFZ0`*C!`@V.!;TER/1=R'*H)"A0T>^?`'*8`(S,`JB1^9I<R,:KT>#I
M!@D0!GB0P7B0^9I<R')X!QJ=`'*8`&2`!RP0!GB0^9I<R,:K)"A0T>\/GFZ0
M`&&`!RS0X%C06X),WX4LA["UXB.?`'*8`(S,`F&`!YFOR9T\&T%GFKN6$Q0:
MZAG&5\#ZP9LD;!11R'C@%V?PP2^`!W[1%L6/+3_[P>61N<6/+5XQ!A]<'F3`
M',6/+3SQP?;$',6/+:C]P1E1!Q]<_-@R!Y_RP1GQ*111R$`Q!A_\`D#!',6/
M+:YQ!A_\`J[1%L6/+14&!Q_\`A4V0,6/+;C$!A^\2:Y#$84L&*[SP>&!2T11
M_-BB<W;PP2^@<W9`$85,;`/XP>&A<W9`$85,51_\`E1%$85<*VSPP1FACQ11
MR/7,!A\<X411_-A2*W+PP1F!!G11_-A2SW+PP1%.%\6/+5["!A_\`EY"%,6/
M+5XB!Q_\`EY"%\6/+7+0$Q_\`G+0$Q11R'*`/1_\`G*`/111R*GSP>61>,6/
M+7;RP2^04\6/+6CSP2\@-\6/+7B`-A_\`G@@-YE_(Z:)Y-@"K&*@T>8D;'.`
M$84,K',@!AIM3L(V!QA1R!4&!V*@T1-\01A1R%'V-AK]1Z<Q!QA1R`U$!F*@
MT0G00,.!$86\%9ZBT7_T&7.`$84,K'>@T>8D;'-P!\6/+14&!QH]P1=T!\6/
M+5$6!G>@T7]T&G-P!\6/+0U$!G>@T0G00,-Q!\6/+5LA81K]1Y\Q!W>0^9I,
MY"TD-XWU/]AR+&RP!4#1!='B&`6MOY2<P<8Z.VL:R9-<T>A_TM!\!Z#TP:##
MO/\CTM@B8P-4T.U4E6\S!F30!7B`WA\,S7<`2IBV!<1%!FH_!UV`WA\,S7<`
M2IBV!</1!6F`WA\,S7<`2IBV!7,@!ET`!^C]P=!\!TZ-+3(V0"\@8P-DK+.S
MIE$-S7<`2B*-+:U3*Q0AXMI2E6\S!F30!7B`WA\,S7<`2IBV!<1%!FH_!UV`
MWA\,S7<`2IBV!</1!6F`WA\,S7<`2IBV!7,@!ET`!^C]P=!\!TZ-+:U3*Q31
M.K62&5DZ.VL:U=!\!Z`DTK8U!3%OFG14NVM`PU.`ZIF1I9-)H2CX?;/1GZ,J
MX:;9/H2Z%00C,N?\.E-Q-V51JT[V<R_@)4&T:UA(H?A33-@R!UM@)&K/!G+P
MHKC(`CV!WA]\(S&P%7<`2M@B!UN`(VK/!G+PHKC(`CV!WA]\(S&P%7<P_9Y?
MNX!;A:8I:6+2/H2Z%01#PZ`5V%<F17XM=1Q!+',8MIO"%>1:>[5F!L>%G<-B
M6XN/AM-CFJG.0CQ\=/K+X.W43ENP0&K_-F-`!FJOCVK/`B>N](#Q`ENP[VJ_
M[SJH_Z:93^;O!D..!?M=NVM@FG*WH\5LFBL=79":IF$R)O8O/\-!PV?Q&B*H
MEL!GGD%AK&$R)D>'R3=BK!QN@RQPWDM_(S&P%7<`2I.\!6\S!F30!7B`WA]\
M(S&P%7<`2I.\!<1%!FH_!UV`WA]\(S&P%7<`2I.\!</1!6F`WA]\(S&P%7<`
M2I.\!7,@!ET`!^C]P3<2`UMQ!Z`TR16-_B(NR2RPXB//`L8Z.VN*`HS\_N:/
M`BR`BRBPY2HP`DK?X%XDU:YQ!Z`DTI.\!2/`!2J@]"=](S&P%7?@U).\XB//
M`L8Z.VN*`HS\_N:/`BR`BRBPY2HP`DK?X%YTN\S[/UK]!C&P%7<`2IBV!6\S
M!F30!7A`R2<-S7<`2IBV!<1%!FH_!UU`R2<-S7<`2IBV!</1!6E`R2<-S7<`
M2IBV!7,@!ET`!Y1\TM!\!Z"$:5OP-F-`!EV`!^C]P=!\!Z"$:5M`7&2@]G/0
M!>C]P=!\!Z"$:5LP'%V0!NC]P=!\!Z"$:5LP!V+0!7"`WA\,S7?@U-BB[^^N
M]ON.X$KB^"P`]XR<&5DZ.VN*`@;__OH+YR.@`F-O@RR@@UO``B20^^G?X-EM
M@RR0R%M@@RQPWDL/S7<`2AN]!;A(R2<-S7<`2A\,.LS[/[8E!'GP=F*2ZFIY
MQC1\%J\A@FH)?.;Y=WGP=F*BW%B@U9Z2!US!X3;(`N>]]#<2`ULA!J`TR5OP
M-F-`!FJOCUV`WA]\(S&P%6(`2I-<T>@OXI+,`BL^\BQ@FD&QI2C`R.]O_BC`
M`KB(`ENN`B.@]`V.!9=>!G<`2A\,S7<`2B(]R5LP`BJ@]"=](S&P%6+@U).\
MXB//`J89%%N*`HS\_N:/`BR`BRBPY2HP`DK?X%YTN\S[/UK]!C&P%6(`2IBV
M!6\S!F2@]OK8!91\TM!\!Z"$:5OP-F-`!FJOCUV`WA\,S7?@U-BB[^^N]ON.
MX$KB^"P`]XQ,%7EPFFN*`@;__OH+YR.@`F-O@RR@@UO``B20^^G?X-EM@RR0
MR%M@@RQPWDL/S7<`2AN]!;A(R2<-S7<`2A\,.LS[/[;U2O1EVZ/26V\`(#3\
M2O1EVZ/26V]PPK1\/C\V$T21S]>4>)&=1Y,^U7<`2A\,H#3[/[9E!&BC3&00
M&BKTNT1$PTFP128I3E/B!B:A,GO#-?\AEAB6)*##O/_S`C:X[VH_!D`Q!UU`
M'$L?W.U*;$B.:5N*:5LJ3I&<),'=KL2VTM&UH%8_R@@4*S1\%J^A3`!*LP0F
M7VK23<PW;NM<]33[/S6+2D#_/^W$`ELP`BJ@]"?MZ@<T!AX\(IJ,R:Y^0&/0
MR6!W0"GXF78MVS.;A:?4L^'SNLB^^&AHH0!*LXV_!?NN]ON^Z%)8X"R`X"RP
M!2.@`FHOA2SN^"0`]_B6!%20`#S`R#Y@\#S`!3,0P`E_0-HC`[R)[().&+Y$
M%RCP:)F1I;.S*XZ!`K(CA^&V0+*#;0ND*:Y13#IP0-HC`_KK`_K^[FJ_[SK(
MZ*@YYUV``BLN+2G``R_@`SS`R#Y@\#Q0_"_@`_K^[FJ_[SK(Z*@YYTKO`SS`
MR`&LOSYPR$`195U`'-*"`BLN+2G``YC&R#Y@\#R0^0>D/3.@OSY0X#R0E2R>
M`CSP`C[``S[`R#R0^0>D/3,PIV41!-_N0F;`$']\0-HS`_KK`P5^_BC``_<.
MYRAP_KG_`C[``XSL`\2?\`>D/32@OSY0X#R0E2R>`CSP`C[``S[`R#R0^0>D
M/31@6S2`[-LE*UB0)`>D/32@OSZP!2AP_F-O@UP@ICZPZ%P@IEW``R_@`SS`
MR#[``\7_`CY0X#R0E2R>`CSP`C[``XSL`SQ0_"_@`SSP`C[``CP`_UXT10`"
MQBY'!YXW&W&3);N94.?"4"*24V\55W,%$13U(LL!`C-22(&U48[240DQ5I1R
M*VJU'6PU)55R)<8L.W?@)6#B4F1R4S*5>.L#6&00)V<B(CDE2#12CSIG!CWU
M4X)"*(:"*(HR!HSR\I$R5I1R*U)%%%1E&E8%*@JO5:;"$JE"(_6H<V90+`H3
M5C$W5I1R*[E"U&FE*O6H<V90+&W%&#A``W.5TFAU5]-2+7N%+=K"+2E!(_6H
M<V8@6">04.>R3NNB`BJ0=JDX!D>)14&)&3`P5RFB`S1``SHP`S)@(D6)`P7A
MD8'F`JYQ!X^*%4&)&3)0`R```S&@`S%0`SI``S1@(L-9$"J@`BJ@`BJ@`BJ@
M`BJ@`BJ@`BJ@`BI0$"J@`FEW(C#``B>B(BJ@`BJ@`C`!$R^@`BJ@`BJ0=JV#
MW,RAFJQY=RJ@`BJ@`KD($P41`A#IOBPB%E@P!$U`!%.@6#(``S!P:6DW$Z."
M2^?C!A8$*JM41Y(SE@*3.NH7R0@Q`N[+(F*!!;YSL5.0`#)0`S9P:6DW$Q&2
M)FY09?_!'#^+AU9FEF@A.4&1BY!R')!R'!21=C,17V00&G\"<Z:>BP7AD29"
MIRQP(BKRD3`!$R^@`BJ@`BJ0=JV#W,RAFJQY=RJ@`BJ@`KD($P41`A#IOBPB
M%E@P!$U`!%.@6#4``S!P:6DW$Z."2^?C!A8$*JM41Y(SE@*3.NH7R0@Q`N[+
M(F*!!;YSL5.0`#)0`S9P:6DW$Q&2)FY09?_!'#^+AU9FEF@A.4&1BY!R')!R
M'!21=C,17V00&G\"<Z:>BP6A`BJ@`BJ@`BJ@`BJ@`BJ@`BJ@`BJ@`@6A`BJ0
M=LEB`RP0`S4@`W>G`BJ@`C`!$R^@`BJ@`BJ0=DOJ.IXN,%^FFJQY=RJ@`BJ0
MBS!1$"$`D>[+(E#P!$_P'DF@!460`#8``S```Y>6=BZ5ZA,!^RT@8\=VY'<7
MR0@Q`N[+(E>P3E.@6`9R:6DW$Q&R8N2,R[7D<IPB1Y!31Y*3F9&,$"/@OBPB
M!;69!$V0!%2@6#)0`S9P:6DW$Q&2TM""DW4D.5@A!>R1BS`Q`N[+(F*!!4L#
M-4B0`#(``Y>6=C,Q*KAT/GO0!Q#Q4+&TC[!R=Y'LD29"`S;``C%0`S+P$!X)
M$S#Q`BJ@`BJ@`FFWI*[CZ0+S9:K)FG>G`BJ@`KD($P41`A#IOBP"!4_P!.^1
M!%I0!`D@`S```S```Y>6=BZ5ZA,!^RT@8\=VY'<7R0@Q`N[+(E>P3E.@6`9R
M:6DW$Q&R8N2,R[7D<IPB1Y!31Y*3F9&,$"/@OBPB!;69!$V0!%2@6#)0`S9P
M:6DW$Q&2TM""DW4D.5@A!>R1BS`Q`N[+(F*!!4L#-4B0`#(``Y>6=C,Q*KAT
M/GO0!Q#Q4+&TC[!R=Y&L`BJ@`BJ@`BJ@`BJ@`BJ@`BJ@`BJ@`@6A`BJ0=C80
ML2Q@`S10`W>G`BJ@`C`!$XIU&B58[CIP:6EG9ESX[705*GAP7ICA&G>0=;D(
M$XJ5`"I`:"NP`CUM%B9#!4F!!2$``HJ5`#"A6*=1@B>@`HQW:6D'`[L8$<3^
MB7NQ/CHV;%J6Q:'Q+!&1BS"A6.`Y$2CP.EM!:#V=*$Y0!4S`!&/Z`FDG(FFG
M%\1R.GM<VZQ\=Y&,$(JE6'E9.<R6TG*P`Y>6=@AA9ERHH]=$%&F7BP7AD3X9
ML2Q@`S2@(A\)$S"A6*=1@N6N`Y>6=F;&A=].5Z&"!^>%&:YQ!UF7BS"A6`F@
M`H2V`BO0TV9A,E20%%@0`A1"(0DQ0P%1!V60%%@0`I!R'""@6*=1@B>@`HQW
M:6D'`[L8$<3^B7NQ/CHV;%J6Q:'Q+!&1BS"A6.`Y$2CP.EM!:#V=*$Y0!4S`
M!&/Z`FDG(FFG%\1R.GM<VZQ\=Y&,$(JE6'E9.<R6TG*P`Y>6=@AA9ERHH]=$
M%&F7BP6A`BJ@`BJ@`BJ@`BJ@`BJ@`BJ@`BJ@`@6A`BJ0=CEP(BR0`T1Y=RJ@
M`BH`$R?L!DEQ'")^'!21=D;@$[5"%:OIB=!B8[==%KE8$!:#$%\PV\."8RB0
M`DEQ'`EQVRC@!BF0%,<!`B*-$`7AD2"0`\G"`CE`E`_AD06A`BJ@`BJ@`BJ@
M`BJ@`BJ@`BJ@`BJ@`@6A`BJ0=BF2("R0(CDP5RJ@`BJ@`@7AD29B`PG"`BF2
M`W/UD0A%6.?"4"*24S&``S0P5Q!!42^R'"`P(ZFH<V:@(TC5&I&R5!\%52)5
MCSIG!L524E5R)<8L.W?@)6#B4F1R4S*5>.M#(_6H<V80)V<B(CDE2#[_4!_1
M4S\E*(1B*(BB*&/`*"\?*6-%*;<B541!5:9A5:"B\%IE*BR1*C[_4!]1+`H3
M5C$W5I1R*[E"U&G%)';R$<725HQ!`S1`5VAU5]-2+7N%+=K"+2GA\P_U$8)U
M`@EU+NNT+GQ0$'R@6#_4$;/A4"5B-`7!!P7!!_V2C_L(*R;RCP7!!WZTG<L,
M0@GP!3-Q0\;Q!3,1$,5A3L*6`&&`!RPP`E9M3L*6`%?)`B/P!3-Q0UB0`'B`
M-A.,!RPP!O&<`#\[P7C``F$0SPF@!@D0`V;@1YH"2C&@`PF`!VB3`&&`!RP0
M!O&<`."*4(1U+@PE(CF5+#0P42WR(LL!`C-B)Q^A(TC5&I&R5!\%5<!B)Q]1
M+"55)5=BS+)S!UX")BY%)C<E4XFW/C[_4!\1)V<B(CDE2#[_4!A4,'X"*()"
M*(:"*(HR!HSR\I$R5I1R*U)%%%1E&E8%*@JO5:;"$JGB\P^%004#5K$2<V-%
M*;>2*T2=5DQB)QA4,,:"`C)0`S.@(BF-5G<U+=6R5]BB+=R2$C[_4!A4,"`P
M+B>04.>R3NO"!_V2C_L(*R;RCP7!!G*A`\!:HBPP`C"P`\!:HBPP`C'`!W^8
M=7:R6MJ4GM:(&3@&1*MI!F6"!7P@^%E<.P$S=C?O7`P!I';R/PG`!ZV?ZG52
MAW4];KG35*[#?SDVG07!!\P2V!YWW!91*W9=C)F>?P7!!SWB);#U^JC.J9X:
M*P7!!YGRP=?EI*[!-;($-SK0EWXT^FV@6`G0`XJ5`,Q7$%&K6,41M8J5*`;R
M'`G`!G*1`#J0`'S`Z856TSM=$&P@%XHOF5?)!T&'^F\T)-TE=VP@%SH`GI)Y
ME0G`!^CC8G.@9!=A$@7!!G*!@UHT!@EPE2#`!S8VSMC*$R7J1SR1`%>9``?!
M$R6:`'R0342AZK(1Q>F9JL_!!\P2V')XH<+^/W)+MPD0!BSPP2PP!L$+`@LD
M=RXPVJ_A!@D0!BSPP2PP!L$+`@NTTEB0`-NYS&(7!@LD!I&[,+U;$&P@%TD2
M8%VTG:'!@5C`!G*1)`'618ZD,@7!!G*1)`'61<\18,.R!@%MFD%Q%`418,.R
M!@%MK&[10P$V+&L0T,;J%HY4$%$;T,8*`C"`!S%@!@MCK,_%!G*Q0&P@%RZP
M0&P@%R[`!G*Q,,8*,V>$!7Q0_[0><J%>4##T!HX.O3*P`ELP`UT@IP4%0V_@
MZ#%@`C(@IP4%0V_@Z#%0`C(@IP4%0V_0`S$P+C)0$`GG)3T@XSX@`P61<%[2
M`S(N`P61<%[2`S'``S)0$`GG)3T0`X@B`P61<%[2`S'@PC)0$`GG)3T0`C)0
M$'Q`@7N^,,8*`HK5R"R@6#+``C.P0%NI$`ND$#60$"Q@`P7!!_)KMI&=1PO3
MNPM#!J'!@>SBIO_C`KU;$'S`+(%=A85^V;7:/VY1^AE33'P`PLNLNT'O4.\H
MOV9;J_WC%J6?,<7$!\M)GXC/M+7:/VY1^AE33'Q`;V8;W.U*;$C^:*;Q/U,)
M!V3JF1HZ,8\&PO\SE7!`IIZIH1/S:,9=$%,)!V3JF1HZ,8\&&/\SE7!`IIZI
MH07!!^`'6[MR>FFF2T28>)[IQQ/S:*;Q/\":`%?)`@8R,8\&PO\#K`EPE2Q@
M(!/S:,9=$,":`%?)`@8R,8\&&/\#K`EPE2Q@(`7!!YH8/Z>79KJ$ZOG=4OS%
M&A/S:*;Q/XZ4!YIC(!/S:"#\/XZ4!UR1``8R,8\V<__C2'G`%0E@(!/S:`FA
M,GZ4`(Z4!URA6"8"D%C`!X-&/EBD8YX8SPE`['Y$[&X@NEB0`,0NNEB0`,3^
MSEB0`,0N=WR034GI!O7F`KV[,("/8=L9&AS(+H"/88ZD,@L#^!C&!R`<&BKT
MY!%V&EI8J_WC%J6?,<7$!PS&<?_QJG[DN&&;`#"`!ZS)FF9`P!/Q<0415G*W
M)L`D/1/Q<0415D<X$1]7$&L"3.S2NP7!!T&:56!B)0&CY]!2$,":`%?)`E=9
M$,":`%?)`J6)!\4$K`EPE2P@K5=93,":`%?)`M)ZE8:9!L5D$G.0`%?)`J/_
M$EA@$G.0`%?)`M-:3"8Q!PEPE2P@K6)`K05A$G.0`%?)`M(J!B:O<[/_:#/W
M/R8Q!PEPE2PP^B^1,X\V<_]C$G.0`%?)`M,Z^X\V<_]C$G.0`%?)`M(J!M0Z
M,8\V<_]C$G.0`%?)`M(J!B:O<\4$K`EPE2PP`@92$,":`-)ZE2G``B-@(`4!
MK`D@K5=YHFF0`BPP`@92$,":`!QB!.I!!:6)!RG``B-@(`4!K`G`(4:@'E10
MFB8*IRPP`@92$'SPVA(6/ZKEB<AJAA0:ZE@P30G`!G)1$%,)!PE@(`4QE7"0
M`#%@!@6A!@E@(`6A!@D0`V:0-;.1!@D`!*@M01/S:(#Q/Y*;`$"`VA)4$#&@
M`Y([P=BV0&!A!@/^:!/\/Y*;`$"`VA*4-;.1`%\P0J+1&EDS&PD`!*@M05DS
M&PD`!#90FGA03-,T3%=93-,$`D!0FG@P^X\&PO\S30D`!#50FGA03'Q0L'@8
M2TO:0BA@K,4$K'>0`&&`!PLT`C)0$,!Z!PD0!GBP0",`NS-``S50$,!Z!PD0
M!G@0N7?\+`4!K'>0`&&`!PL4&`4!K'>0`&&`!PM4JVE03,!Z!PD0!GBP0-!J
M`]-:3,!Z!PD0!GBP0"/0`C8PK<4$K'>0`&&`!PLTK2>:!L4$K'>0`&&`!PL$
MK38PK2>:!L4$K'>0`&&`!PLT`LDRK2>:!L4$K'>0`",@K6)`K>`<SWQ0L'@8
M2TO:0J69!R123,`J!@F`&@ND`C)0$,`J!@DPK2D`SAQ:4,(F!@F@`M(J!M0*
MSAQ:4,(F!@F@`C@PK2FP0"/`?'4@=WRP-Z^\^$V'!5Y"%V&`!Y'+H>PBS(E:
M$'S`+(&M*0J/7&1>VZ+]CE-=$&P@%\51$,1>$,!Z!\]QDQ1<$,#J%GBP0#&@
M`C)0$,!Z=S*@`C-PFUT`SO',!S;6;+/QG[4+N%+$1P?$RK<;=#-5C,U1$,!:
MHBPP`C&P`\#J%GC``B,``WP@^.4H=D_G.I)A=40!.7QT0$J14.?"4"*24S)0
M`S.@(A!!42^R'"`P(W:"006S48[240DQ5I1R*\!B)QA4,%)B4E=BS+)S!UX"
H)BY%)C<E4XFW/C[_4!A4,#<U5I1R*\G+)D4"*YPA!W[AG<9SVR``D+)S
`
end
-------------------------------------------------------------------------------
-- 
Earl Chew, Dept of Computer Science, Monash University, Australia 3168
ARPA: cechew%bruce.cs.monash.oz.au@uunet.uu.net  ACS : cechew@bruce.oz
----------------------------------------------------------------------

cechew@bruce.OZ (Earl Chew) (11/16/89)

From article <1691@bruce.OZ>, by cechew@bruce.OZ (Earl Chew):
> This posting contains a uuencoded compressed (12 bits) shar file (I did it this
> way):

In case there's some confusion ---

You will probably find that you will have to port Minix sed in order to use the
sed script. The Unix seds that I have tried it on either will not allow long
labels or have internal arrays that are too small to handle such large scripts.

Porting Minix sed should not prove too difficult. I just compiled mine under TC
and squinted as the warning messages flew past :-) The patches enclosed are
necessary to increase the sizes of the internal arrays so that Minix sed will
run the script. I suppose if you have the source to Unix sed, you could try
fixing the problems :-)

Earl
-- 
Earl Chew, Dept of Computer Science, Monash University, Australia 3168
ARPA: cechew%bruce.cs.monash.oz.au@uunet.uu.net  ACS : cechew@bruce.oz
----------------------------------------------------------------------

cechew@bruce.OZ (Earl Chew) (11/17/89)

From article <1692@bruce.OZ>, by cechew@bruce.OZ (Earl Chew):
> Porting Minix sed should not prove too difficult. I just compiled mine under TC
> and squinted as the warning messages flew past :-) The patches enclosed are
> necessary to increase the sizes of the internal arrays so that Minix sed will
> run the script. I suppose if you have the source to Unix sed, you could try
> fixing the problems :-)

Oops... I spoke too soon. I believe that there are *many* problems with the old
Minix sed (NULL dereferencing and the like). Here is the version off the net
with the bigger poolsize and command array length. It was posted by Peter
Housel I think.

Earl

-------------------------------------------------------------------------------
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  sed.c
# Wrapped by cechew@bruce on Fri Nov 17 12:32:07 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'sed.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'sed.c'\"
else
echo shar: Extracting \"'sed.c'\" \(45843 characters\)
sed "s/^X//" >'sed.c' <<'END_OF_FILE'
X/* sed - stream editor		Author: Eric S. Raymond */
X
X/* This used to be three different files with the following makefile:
X * (Note the chmem).
X
XCFLAGS=	-F -T.
X
XOBJS=   sedcomp.s sedexec.s
X
Xsed: 	$(OBJS)
X        cc -T. -o sed $(OBJS)
X	@chmem =13312 sed
X
X$(OBJS):	sed.h
X
X * If you want longer lines: increase MAXBUF.
X * If you want scripts with more text: increase POOLSIZE.
X * If you want more commands per script: increase MAXCMDS.
X */
X
X#include <stdio.h>
X#include <ctype.h>
X
X/*+++++++++++++++*/
X
X/* sed.h -- types and constants for the stream editor */
X
X/* data area sizes used by both modules */
X#define MAXBUF		4000	/* current line buffer size */
X#define MAXAPPENDS	20	/* maximum number of appends */
X#define MAXTAGS		9	/* tagged patterns are \1 to \9 */
X
X/* constants for compiled-command representation */
X#define EQCMD	0x01	/* = -- print current line number	*/
X#define ACMD	0x02	/* a -- append text after current line	*/
X#define BCMD	0x03	/* b -- branch to label			*/
X#define CCMD	0x04	/* c -- change current line		*/
X#define DCMD	0x05	/* d -- delete all of pattern space		*/
X#define CDCMD	0x06	/* D -- delete first line of pattern space	*/
X#define GCMD	0x07	/* g -- copy hold space to pattern space	*/
X#define CGCMD	0x08	/* G -- append hold space to pattern space	*/
X#define HCMD	0x09	/* h -- copy pattern space to hold space	*/
X#define CHCMD	0x0A	/* H -- append pattern space to hold space	*/
X#define ICMD	0x0B	/* i -- insert text before current line		*/
X#define LCMD	0x0C	/* l -- print pattern space in escaped form	*/
X#define NCMD	0x0D	/* n -- get next line into pattern space	*/
X#define CNCMD	0x0E	/* N -- append next line to pattern space	*/
X#define PCMD	0x0F	/* p -- print pattern space to output		*/
X#define CPCMD	0x10	/* P -- print first line of pattern space	*/
X#define QCMD	0x11	/* q -- exit the stream editor			*/
X#define RCMD	0x12	/* r -- read in a file after current line	*/
X#define SCMD	0x13	/* s -- regular-expression substitute		*/
X#define TCMD	0x14	/* t -- branch on any substitute successful	*/
X#define CTCMD	0x15	/* T -- branch on any substitute failed		*/
X#define WCMD	0x16	/* w -- write pattern space to file		*/
X#define CWCMD	0x17	/* W -- write first line of pattern space	*/
X#define XCMD	0x18	/* x -- exhange pattern and hold spaces		*/
X#define YCMD	0x19	/* y -- transliterate text			*/
X
Xstruct	cmd_t				/* compiled-command representation */
X{
X	char	*addr1;			/* first address for command */
X	char	*addr2;			/* second address for command */
X	union
X	{
X		char		*lhs;	/* s command lhs */
X		struct cmd_t	*link;	/* label link */
X	} u;
X	char	command;		/* command code */
X	char	*rhs;			/* s command replacement string */
X	FILE	*fout;			/* associated output file descriptor */
X	struct
X	{
X		char allbut  ;	 /* was negation specified? */
X		char global  ;	 /* was g postfix specified? */
X		char print   ;	 /* was p postfix specified? */
X		char inrange ;	 /* in an address range? */
X	} flags;
X};
Xtypedef struct cmd_t	sedcmd;		/* use this name for declarations */
X
X#define BAD	((char *) -1)		/* guaranteed not a string ptr */
X
X
X/* address and regular expression compiled-form markers */
X#define STAR	1	/* marker for Kleene star */
X#define CCHR	2	/* non-newline character to be matched follows */
X#define CDOT	4	/* dot wild-card marker */
X#define CCL	6	/* character class follows */
X#define CNL	8	/* match line start */
X#define CDOL	10	/* match line end */
X#define CBRA	12	/* tagged pattern start marker */
X#define CKET	14	/* tagged pattern end marker */
X#define CBACK	16	/* backslash-digit pair marker */
X#define CLNUM	18	/* numeric-address index follows */
X#define CEND	20	/* symbol for end-of-source */
X#define CEOF	22	/* end-of-field mark */
X
X/* sed.h ends here */
X
X#define CMASK  0xFF	/* some char type should have been unsigned char? */
X
X/*+++++++++++++++*/
X
X/* sed - stream editor		Author: Eric S. Raymond */
X
X/*
X   The stream editor compiles its command input	 (from files or -e options)
X   into an internal form using compile() then executes the compiled form using
X   execute(). Main() just initializes data structures, interprets command line
X   options, and calls compile() and execute() in appropriate sequence.
X   
X   The data structure produced by compile() is an array of compiled-command
X   structures (type sedcmd).  These contain several pointers into pool[], the
X   regular-expression and text-data pool, plus a command code and g & p flags.
X   In the special case that the command is a label the struct  will hold a ptr
X   into the labels array labels[] during most of the compile,  until resolve()
X   resolves references at the end.
X
X   The operation of execute() is described in its source module.
X*/
X
X/* #include <stdio.h>		/* uses getc, fprintf, fopen, fclose */
Xextern FILE *fopen();		/* should this be in stdio.h? */
X/* #include "sed.h"		/* command type struct and name defines */
X
X/* imported functions */
Xextern int strcmp();		/* test strings for equality */
Xextern void execute();		/* execute compiled command */
X
X/***** public stuff ******/
X
X#define MAXCMDS		500	/* maximum number of compiled commands */
X#define MAXLINES	256	/* max # numeric addresses to compile */ 
X
X/* main data areas */
Xchar	linebuf[MAXBUF+1];	/* current-line buffer */
Xsedcmd	cmds[MAXCMDS+1];	/* hold compiled commands */
Xlong	linenum[MAXLINES];	/* numeric-addresses table */
X
X/* miscellaneous shared variables */ 
Xint	nflag;			/* -n option flag */
Xint	eargc;			/* scratch copy of argument count */
Xchar	**eargv;		/* scratch copy of argument list */
Xchar	bits[]		= {1,2,4,8,16,32,64,128};
X
X/***** module common stuff *****/
X
X#define POOLSIZE	20000	/* size of string-pool space */
X#define WFILES		10	/* max # w output files that can be compiled */
X#define RELIMIT		256	/* max chars in compiled RE */
X#define MAXDEPTH	20	/* maximum {}-nesting level */
X#define MAXLABS		50	/* max # of labels that can be handled */
X
X#define SKIPWS(pc)	while ((*pc==' ') || (*pc=='\t')) pc++
X#define ABORT(msg)	(fprintf(stderr, msg, linebuf), quit(2))
X#define IFEQ(x, v)	if (*x == v) x++ , /* do expression */
X
X/* error messages */
Xstatic char	AGMSG[] = "sed: garbled address %s\n";
Xstatic char	CGMSG[] = "sed: garbled command %s\n";
Xstatic char	TMTXT[] = "sed: too much text: %s\n";
Xstatic char	AD1NG[] = "sed: no addresses allowed for %s\n";
Xstatic char	AD2NG[] = "sed: only one address allowed for %s\n";
Xstatic char	TMCDS[] = "sed: too many commands, last was %s\n";
Xstatic char	COCFI[] = "sed: cannot open command-file %s\n";
Xstatic char	UFLAG[] = "sed: unknown flag %c\n";
Xstatic char	CCOFI[] = "sed: cannot create %s\n";
Xstatic char	ULABL[] = "sed: undefined label %s\n";
Xstatic char	TMLBR[] = "sed: too many {'s\n";
Xstatic char	FRENL[] = "sed: first RE must be non-null\n";
Xstatic char	NSCAX[] = "sed: no such command as %s\n";
Xstatic char	TMRBR[] = "sed: too many }'s\n";
Xstatic char	DLABL[] = "sed: duplicate label %s\n";
Xstatic char	TMLAB[] = "sed: too many labels: %s\n";
Xstatic char	TMWFI[] = "sed: too many w files\n";
Xstatic char	REITL[] = "sed: RE too long: %s\n";
Xstatic char	TMLNR[] = "sed: too many line numbers\n";
Xstatic char	TRAIL[] = "sed: command \"%s\" has trailing garbage\n";
X 
Xtypedef struct			/* represent a command label */
X{
X	char		*name;		/* the label name */
X	sedcmd		*last;		/* it's on the label search list */  
X	sedcmd		*address;	/* pointer to the cmd it labels */
X}
Xlabel;
X
X/* label handling */
Xstatic label	labels[MAXLABS];	/* here's the label table */
Xstatic label	*lab	= labels + 1;	/* pointer to current label */
Xstatic label	*lablst = labels;	/* header for search list */
X
X/* string pool for regular expressions, append text, etc. etc. */
Xstatic char	pool[POOLSIZE];			/* the pool */
Xstatic char	*fp	= pool;			/* current pool pointer */
Xstatic char	*poolend = pool + POOLSIZE;	/* pointer past pool end */
X
X/* compilation state */
Xstatic FILE	*cmdf	= NULL;		/* current command source */
Xstatic char	*cp	= linebuf;	/* compile pointer */
Xstatic sedcmd	*cmdp	= cmds;		/* current compiled-cmd ptr */
Xstatic char	*lastre = NULL;		/* old RE pointer */
Xstatic int	bdepth	= 0;		/* current {}-nesting level */
Xstatic int	bcount	= 0;		/* # tagged patterns in current RE */
X
X/* compilation flags */
Xstatic int	eflag;			/* -e option flag */
Xstatic int	gflag;			/* -g option flag */
X
X
Xmain(argc, argv)
X/* main sequence of the stream editor */
Xint	argc;
Xchar	*argv[];
X{
X	void compile(), resolve();
X
X	eargc	= argc;		/* set local copy of argument count */
X	eargv	= argv;		/* set local copy of argument list */
X	cmdp->addr1 = pool;	/* 1st addr expand will be at pool start */
X	if (eargc == 1)
X		quit(0);	/* exit immediately if no arguments */
X	/* scan through the arguments, interpreting each one */
X	while ((--eargc > 0) && (**++eargv == '-'))
X		switch (eargv[0][1])
X		{
X		case 'e':
X			eflag++; compile();	/* compile with e flag on */
X			eflag = 0;
X			continue;		/* get another argument */
X		case 'f':
X			if (eargc-- <= 0)	/* barf if no -f file */
X				quit(2);
X			if ((cmdf = fopen(*++eargv, "r")) == NULL)
X			{
X				fprintf(stderr, COCFI, *eargv);
X				quit(2);
X			}
X			compile();	/* file is O.K., compile it */
X			fclose(cmdf);
X			continue;	/* go back for another argument */
X		case 'g':
X			gflag++;	/* set global flag on all s cmds */
X			continue;
X		case 'n':
X			nflag++;	/* no print except on p flag or w */
X			continue;
X		default:
X			fprintf(stdout, UFLAG, eargv[0][1]);
X			continue;
X		}
X
X
X	if (cmdp == cmds)	/* no commands have been compiled */
X	{
X		eargv--; eargc++;
X		eflag++; compile(); eflag = 0;
X		eargv++; eargc--;
X	}
X
X	if (bdepth)	/* we have unbalanced squigglies */
X		ABORT(TMLBR);
X
X	lablst->address = cmdp; /* set up header of label linked list */
X	resolve();		/* resolve label table indirections */
X	execute();		/* execute commands */
X	quit(0);		/* everything was O.K. if we got here */
X}
X
X
X#define H	0x80	/* 128 bit, on if there's really code for command */
X#define LOWCMD	56	/* = '8', lowest char indexed in cmdmask */ 
X
X/* indirect through this to get command internal code, if it exists */
Xstatic char	cmdmask[] =
X{
X	0,	0,	H,	0,	0,	H+EQCMD,0,	0,
X	0,	0,	0,	0,	H+CDCMD,0,	0,	CGCMD,
X	CHCMD,	0,	0,	0,	0,	0,	CNCMD,	0,
X	CPCMD,	0,	0,	0,	H+CTCMD,0,	0,	H+CWCMD,
X	0,	0,	0,	0,	0,	0,	0,	0,
X	0,	H+ACMD, H+BCMD, H+CCMD, DCMD,	0,	0,	GCMD,
X	HCMD,	H+ICMD, 0,	0,	H+LCMD, 0,	NCMD,	0,
X	PCMD,	H+QCMD, H+RCMD, H+SCMD, H+TCMD, 0,	0,	H+WCMD,
X	XCMD,	H+YCMD, 0,	H+BCMD, 0,	H,	0,	0,
X};
X
Xstatic void compile()
X/* precompile sed commands out of a file */
X{
X	char		ccode, *address();
X
X
X	for(;;)					/* main compilation loop */
X	{
X		if (*cp == '\0')		/* get a new command line */
X			if (cmdline(cp = linebuf) < 0)
X				break;
X		SKIPWS(cp);
X		if (*cp=='\0')			/* empty */
X			continue;
X		if (*cp == '#')			/* comment */
X		{
X			while(*cp)
X				++cp;
X			continue;
X		}
X		if (*cp == ';')			/* ; separates cmds */
X		{
X			cp++;
X			continue;
X		}
X
X		/* compile first address */
X		if (fp > poolend)
X			ABORT(TMTXT);
X		else if ((fp = address(cmdp->addr1 = fp)) == BAD)
X			ABORT(AGMSG);
X
X		if (fp == cmdp->addr1)		/* if empty RE was found */
X		{
X			if (lastre)		/* if there was previous RE */
X				cmdp->addr1 = lastre;	/* use it */
X			else
X				ABORT(FRENL);
X		}
X		else if (fp == NULL)		/* if fp was NULL */
X		{
X			fp = cmdp->addr1;	/* use current pool location */
X			cmdp->addr1 = NULL;
X		}
X		else
X		{
X			lastre = cmdp->addr1;
X			if (*cp == ',' || *cp == ';')	/* there's 2nd addr */
X			{
X				cp++;
X				if (fp > poolend) ABORT(TMTXT);
X				fp = address(cmdp->addr2 = fp);
X				if (fp == BAD || fp == NULL) ABORT(AGMSG);
X				if (fp == cmdp->addr2)
X					cmdp->addr2 = lastre;
X				else
X					lastre = cmdp->addr2;
X			}
X			else
X				cmdp->addr2 = NULL;	/* no 2nd address */
X		}
X		if (fp > poolend) ABORT(TMTXT);
X
X		SKIPWS(cp);		/* discard whitespace after address */
X		IFEQ(cp, '!') cmdp->flags.allbut = 1;
X
X		SKIPWS(cp);		/* get cmd char, range-check it */
X		if ((*cp < LOWCMD) || (*cp > '~')
X			|| ((ccode = cmdmask[*cp - LOWCMD]) == 0))
X				ABORT(NSCAX);
X
X		cmdp->command = ccode & ~H;	/* fill in command value */
X		if ((ccode & H) == 0)		/* if no compile-time code */
X			cp++;			/* discard command char */
X		else if (cmdcomp(*cp++))	/* execute it; if ret = 1 */
X			continue;		/* skip next line read */
X
X		if (++cmdp >= cmds + MAXCMDS) ABORT(TMCDS);
X
X		SKIPWS(cp);			/* look for trailing stuff */
X		if (*cp != '\0' && *cp != ';' && *cp != '#')
X			ABORT(TRAIL);
X	}
X}
X
Xstatic int cmdcomp(cchar)
X/* compile a single command */
Xregister char	cchar;		/* character name of command */
X{
X	char		*gettext(), *rhscomp(), *recomp(), *ycomp();
X	static sedcmd	**cmpstk[MAXDEPTH];	/* current cmd stack for {} */
X	static char	*fname[WFILES];		/* w file name pointers */
X	static FILE	*fout[WFILES];		/* w file file ptrs */
X	static int	nwfiles = 1;		/* count of open w files */
X	int		i;			/* indexing dummy used in w */
X	sedcmd		*sp1, *sp2;		/* temps for label searches */
X	label		*lpt, *search();	/* ditto, and the searcher */
X	char		redelim;		/* current RE delimiter */
X
X	fout[0] = stdout;
X	switch(cchar)
X	{
X	case '{':	/* start command group */
X		cmdp->flags.allbut = !cmdp->flags.allbut;
X		cmpstk[bdepth++] = &(cmdp->u.link);
X		if (++cmdp >= cmds + MAXCMDS) ABORT(TMCDS);
X		return(1);
X
X	case '}':	/* end command group */
X		if (cmdp->addr1) ABORT(AD1NG);	/* no addresses allowed */
X		if (--bdepth < 0) ABORT(TMRBR); /* too many right braces */
X		*cmpstk[bdepth] = cmdp;		/* set the jump address */
X		return(1);
X
X	case '=':			/* print current source line number */
X	case 'q':			/* exit the stream editor */
X		if (cmdp->addr2) ABORT(AD2NG);
X		break;
X
X	case ':':	/* label declaration */
X		if (cmdp->addr1) ABORT(AD1NG);	/* no addresses allowed */
X		fp = gettext(lab->name = fp);	/* get the label name */
X		if (lpt = search(lab))		/* does it have a double? */
X		{
X			if (lpt->address) ABORT(DLABL); /* yes, abort */
X		}
X		else	/* check that it doesn't overflow label table */
X		{
X			lab->last = NULL;
X			lpt = lab;
X			if (++lab >= labels + MAXLABS) ABORT(TMLAB);
X		}
X		lpt->address = cmdp;
X		return(1);
X
X	case 'b':	/* branch command */
X	case 't':	/* branch-on-succeed command */
X	case 'T':	/* branch-on-fail command */
X		SKIPWS(cp);
X		if (*cp == '\0')	/* if branch is to start of cmds... */
X		{
X			/* add current command to end of label last */
X			if (sp1 = lablst->last)
X			{
X				while(sp2 = sp1->u.link)
X					sp1 = sp2;
X				sp1->u.link = cmdp;
X			}
X			else	/* lablst->last == NULL */
X				lablst->last = cmdp;
X			break;
X		}
X		fp = gettext(lab->name = fp);	/* else get label into pool */
X		if (lpt = search(lab))		/* enter branch to it */
X		{
X			if (lpt->address)
X				cmdp->u.link = lpt->address;
X			else
X			{
X				sp1 = lpt->last;
X				while(sp2 = sp1->u.link)
X					sp1 = sp2;
X				sp1->u.link = cmdp;
X			}
X		}
X		else		/* matching named label not found */
X		{
X			lab->last = cmdp;	/* add the new label */
X			lab->address = NULL;	/* it's forward of here */
X			if (++lab >= labels + MAXLABS)	/* overflow if last */
X				ABORT(TMLAB);
X		}
X		break;
X
X	case 'a':	/* append text */
X	case 'i':	/* insert text */
X	case 'r':	/* read file into stream */
X		if (cmdp->addr2) ABORT(AD2NG);
X	case 'c':	/* change text */
X		if ((*cp == '\\') && (*++cp == '\n')) cp++;
X		fp = gettext(cmdp->u.lhs = fp);
X		break;
X
X	case 'D':	/* delete current line in hold space */
X		cmdp->u.link = cmds;
X		break;
X
X	case 's':	/* substitute regular expression */
X		redelim = *cp++;		/* get delimiter from 1st ch */
X		if ((fp = recomp(cmdp->u.lhs = fp, redelim)) == BAD)
X			ABORT(CGMSG);
X		if (fp == cmdp->u.lhs)		/* if compiled RE zero len */
X			cmdp->u.lhs = lastre;	/*   use the previous one */
X		else				/* otherwise */
X			lastre = cmdp->u.lhs;	/*   save the one just found */
X		if ((cmdp->rhs = fp) > poolend) ABORT(TMTXT);
X		if ((fp = rhscomp(cmdp->rhs, redelim)) == BAD) ABORT(CGMSG);
X		if (gflag) cmdp->flags.global++;
X		while (*cp == 'g' || *cp == 'p' || *cp == 'P')
X		{
X			IFEQ(cp, 'g') cmdp->flags.global++;
X			IFEQ(cp, 'p') cmdp->flags.print = 1;
X			IFEQ(cp, 'P') cmdp->flags.print = 2;
X		}
X
X	case 'l':	/* list pattern space */
X		if (*cp == 'w')
X			cp++;		/* and execute a w command! */
X		else
X			break;		/* s or l is done */
X
X	case 'w':	/* write-pattern-space command */
X	case 'W':	/* write-first-line command */
X		if (nwfiles >= WFILES) ABORT(TMWFI);
X		fp=gettext(fname[nwfiles]=fp);	/* filename will be in pool */
X		for(i = nwfiles-1; i >= 0; i--) /* match it in table */
X			if ((fname[i] != NULL) && 
X			    (strcmp(fname[nwfiles], fname[i]) == 0))
X			{
X				cmdp->fout = fout[i];
X				return(0);
X			}
X		/* if didn't find one, open new out file */
X		if ((cmdp->fout = fopen(fname[nwfiles], "w")) == NULL)
X		{
X			fprintf(stderr, CCOFI, fname[nwfiles]);
X			quit(2);
X		}
X		fout[nwfiles++] = cmdp->fout;
X		break;
X
X	case 'y':	/* transliterate text */
X		fp = ycomp(cmdp->u.lhs = fp, *cp++);	/* compile translit */
X		if (fp == BAD) ABORT(CGMSG);		/* fail on bad form */
X		if (fp > poolend) ABORT(TMTXT);		/* fail on overflow */
X		break;
X	}
X	return(0);	/* succeeded in interpreting one command */
X}
X
Xstatic char *rhscomp(rhsp, delim)	/* uses bcount */
X/* generate replacement string for substitute command right hand side */
Xregister char	*rhsp;		/* place to compile expression to */
Xregister char	delim;		/* regular-expression end-mark to look for */
X{
X	register char	*p = cp;		/* strictly for speed */
X
X	for(;;)
X		if ((*rhsp = *p++) == '\\')	/* copy; if it's a \, */
X		{
X			*rhsp = *p++;		/* copy escaped char */
X			/* check validity of pattern tag */
X			if (*rhsp > bcount + '0' && *rhsp <= '9')
X				return(BAD);
X			*rhsp++ |= 0x80;	/* mark the good ones */
X			continue;
X		}
X		else if (*rhsp == delim)	/* found RE end, hooray... */
X		{
X			*rhsp++ = '\0';		/* cap the expression string */
X			cp = p;
X			return(rhsp);		/* pt at 1 past the RE */
X		}
X		else if (*rhsp++ == '\0')	/* last ch not RE end, help! */
X			return(BAD);
X}
X
Xstatic char *recomp(expbuf, redelim)	/* uses cp, bcount */
X/* compile a regular expression to internal form */
Xchar	*expbuf;			/* place to compile it to */
Xchar	redelim;			/* RE end-marker to look for */
X{
X	register char	*ep = expbuf;	/* current-compiled-char pointer */
X	register char	*sp = cp;	/* source-character ptr */
X	register int	c;		/* current-character pointer */
X	char		negclass;	/* all-but flag */
X	char		*lastep;	/* ptr to last expr compiled */
X	char		*svclass;	/* start of current char class */
X	char		brnest[MAXTAGS];	/* bracket-nesting array */
X	char		*brnestp;	/* ptr to current bracket-nest */
X	char		*pp;		/* scratch pointer */
X	int		classct;	/* class element count */
X	int		tags;		/* # of closed tags */
X
X	if (*cp == redelim)		/* if first char is RE endmarker */
X		return(cp++, expbuf);	/* leave existing RE unchanged */
X
X	lastep = NULL;			/* there's no previous RE */
X	brnestp = brnest;		/* initialize ptr to brnest array */
X	tags = bcount = 0;		/* initialize counters */
X
X	if (*ep++ = (*sp == '^'))	/* check for start-of-line syntax */
X		sp++;
X
X	for (;;)
X	{
X		if (ep >= expbuf + RELIMIT)	/* match is too large */
X			return(cp = sp, BAD);
X		if ((c = *sp++) == redelim)	/* found the end of the RE */
X		{
X			cp = sp;
X			if (brnestp != brnest)	/* \(, \) unbalanced */
X				return(BAD);
X			*ep++ = CEOF;		/* write end-of-pattern mark */
X			return(ep);		/* return ptr to compiled RE */
X		}
X		if (c != '*') 			/* if we're a postfix op */
X			lastep = ep;		/*   get ready to match last */
X
X		switch (c)
X		{
X		case '\\':
X			if ((c = *sp++) == '(') /* start tagged section */
X			{
X				if (bcount >= MAXTAGS)
X					return(cp = sp, BAD);
X				*brnestp++ = bcount;	/* update tag stack */
X				*ep++ = CBRA;		/* enter tag-start */
X				*ep++ = bcount++;	/* bump tag count */
X				continue;
X			}
X			else if (c == ')')	/* end tagged section */
X			{
X				if (brnestp <= brnest)	/* extra \) */
X					return(cp = sp, BAD);
X				*ep++ = CKET;		/* enter end-of-tag */
X				*ep++ = *--brnestp;	/* pop tag stack */
X				tags++;			/* count closed tags */
X				continue;
X			}
X			else if (c >= '1' && c <= '9')	/* tag use */
X			{
X				if ((c -= '1') >= tags) /* too few */
X					return(BAD);
X				*ep++ = CBACK;		/* enter tag mark */
X				*ep++ = c;		/* and the number */
X				continue;
X			}
X			else if (c == '\n')	/* escaped newline no good */
X				return(cp = sp, BAD);
X			else if (c == 'n')		/* match a newline */
X				c = '\n';
X			else if (c == 't')		/* match a tab */
X				c = '\t';
X			else if (c == 'r')		/* match a return */
X				c = '\r';
X			goto defchar;
X
X		case '\0':	/* ignore nuls */
X			continue;
X
X		case '\n':	/* trailing pattern delimiter is missing */
X			return(cp = sp, BAD);
X
X		case '.':	/* match any char except newline */
X			*ep++ = CDOT;
X			continue;
X		case '*':	/* 0..n repeats of previous pattern */
X			if (lastep == NULL)	/* if * isn't first on line */
X				goto defchar;	/*   match a literal * */
X			if (*lastep == CKET)	/* can't iterate a tag */
X				return(cp = sp, BAD);
X			*lastep |= STAR;	/* flag previous pattern */
X			continue;
X
X		case '$':	/* match only end-of-line */
X			if (*sp != redelim)	/* if we're not at end of RE */
X				goto defchar;	/*   match a literal $ */
X			*ep++ = CDOL;		/* insert end-symbol mark */
X			continue;
X
X		case '[':	/* begin character set pattern */
X			if (ep + 17 >= expbuf + RELIMIT)
X				ABORT(REITL);
X			*ep++ = CCL;		/* insert class mark */
X			if (negclass = ((c = *sp++) == '^'))
X				c = *sp++;
X			svclass = sp;		/* save ptr to class start */
X			do {
X				if (c == '\0') ABORT(CGMSG);
X
X				/* handle character ranges */
X				if (c == '-' && sp > svclass && *sp != ']')
X					for (c = sp[-2]; c < *sp; c++)
X						ep[c >> 3] |= bits[c & 7];
X
X				/* handle escape sequences in sets */
X				if (c == '\\')
X					if ((c = *sp++) == 'n')
X						c = '\n';
X					else if (c == 't')
X						c = '\t';
X					else if (c == 'r')
X						c = '\r';
X
X				/* enter (possibly translated) char in set */
X				ep[c >> 3] |= bits[c & 7];
X			} while
X				((c = *sp++) != ']');
X
X			/* invert the bitmask if all-but was specified */
X			if (negclass)
X				for(classct = 0; classct < 16; classct++)
X					ep[classct] ^= 0xFF;
X			ep[0] &= 0xFE;		/* never match ASCII 0 */ 
X			ep += 16;		/* advance ep past set mask */
X			continue;
X
X		defchar:	/* match literal character */
X		default:	/* which is what we'd do by default */
X			*ep++ = CCHR;		/* insert character mark */
X			*ep++ = c;
X		}
X	}
X}
X
Xstatic int cmdline(cbuf)		/* uses eflag, eargc, cmdf */
X/* read next command from -e argument or command file */
Xregister char	*cbuf;
X{
X	register int	inc;	/* not char because must hold EOF */
X
X	cbuf--;			/* so pre-increment points us at cbuf */
X
X	/* e command flag is on */
X	if (eflag)
X	{
X		register char	*p;	/* ptr to current -e argument */
X		static char	*savep; /* saves previous value of p */
X
X		if (eflag > 0)	/* there are pending -e arguments */
X		{
X			eflag = -1;
X			if (eargc-- <= 0)
X				quit(2);	/* if no arguments, barf */
X
X			/* else transcribe next e argument into cbuf */
X			p = *++eargv;
X			while(*++cbuf = *p++)
X				if (*cbuf == '\\')
X				{
X					if ((*++cbuf = *p++) == '\0')
X						return(savep = NULL, -1);
X					else
X						continue;
X				}
X				else if (*cbuf == '\n') /* end of 1 cmd line */
X				{ 
X					*cbuf = '\0';
X					return(savep = p, 1);
X					/* we'll be back for the rest... */
X				}
X
X			/* found end-of-string; can advance to next argument */
X			return(savep = NULL, 1);
X		}
X
X		if ((p = savep) == NULL)
X			return(-1);
X
X		while(*++cbuf = *p++)
X			if (*cbuf == '\\')
X			{
X				if ((*++cbuf = *p++) == '0')
X					return(savep = NULL, -1);
X				else
X					continue;
X			}
X			else if (*cbuf == '\n')
X			{
X				*cbuf = '\0';
X				return(savep = p, 1);
X			}
X
X		return(savep = NULL, 1);
X	}
X
X	/* if no -e flag read from command file descriptor */
X	while((inc = getc(cmdf)) != EOF)		/* get next char */
X		if ((*++cbuf = inc) == '\\')		/* if it's escape */ 
X			*++cbuf = inc = getc(cmdf);	/* get next char */
X		else if (*cbuf == '\n')			/* end on newline */
X			return(*cbuf = '\0', 1);	/* cap the string */
X
X	return(*++cbuf = '\0', -1);	/* end-of-file, no more chars */
X}
X
Xstatic char *address(expbuf)		/* uses cp, linenum */
X/* expand an address at *cp... into expbuf, return ptr at following char */
Xregister char	*expbuf;
X{
X	static int	numl = 0;	/* current ind in addr-number table */
X	register char	*rcp;		/* temp compile ptr for forwd look */
X	long		lno;		/* computed value of numeric address */
X
X	if (*cp == '$')			/* end-of-source address */
X	{
X		*expbuf++ = CEND;	/* write symbolic end address */
X		*expbuf++ = CEOF;	/* and the end-of-address mark (!) */
X		cp++;			/* go to next source character */
X		return(expbuf);		/* we're done */
X	}
X	if (*cp == '/')			/* start of regular-expression match */
X		return(recomp(expbuf, *cp++));	/* compile the RE */
X
X	rcp = cp; lno = 0;		/* now handle a numeric address */
X	while(*rcp >= '0' && *rcp <= '9')	/* collect digits */
X		lno = lno*10 + *rcp++ - '0';	/*  compute their value */
X
X	if (rcp > cp)			/* if we caught a number... */
X	{
X		*expbuf++ = CLNUM;	/* put a numeric-address marker */
X		*expbuf++ = numl;	/* and the address table index */
X		linenum[numl++] = lno;	/* and set the table entry */
X		if (numl >= MAXLINES)	/* oh-oh, address table overflow */
X			ABORT(TMLNR);	/*   abort with error message */
X		*expbuf++ = CEOF;	/* write the end-of-address marker */
X		cp = rcp;		/* point compile past the address */ 
X		return(expbuf);		/* we're done */
X	}
X
X	return(NULL);		/* no legal address was found */
X}
X
Xstatic char *gettext(txp)		/* uses global cp */
X/* accept multiline input from *cp..., discarding leading whitespace */ 
Xregister char	*txp;			/* where to put the text */
X{
X	register char	*p = cp;	/* this is for speed */
X
X	SKIPWS(p);			/* discard whitespace */
X	do {
X		if ((*txp = *p++) == '\\')	/* handle escapes */
X			*txp = *p++;
X		if (*txp == '\0')		/* we're at end of input */
X			return(cp = --p, ++txp);
X		else if (*txp == '\n')		/* also SKIPWS after newline */
X			SKIPWS(p);
X	} while
X		(txp++);		/* keep going till we find that nul */
X	return(txp);
X}
X
Xstatic label *search(ptr)			/* uses global lablst */
X/* find the label matching *ptr, return NULL if none */
Xregister label	*ptr;
X{
X	register label	*rp;
X	for(rp = lablst; rp < ptr; rp++)
X		if ((rp->name != NULL) && (strcmp(rp->name, ptr->name) == 0))
X			return(rp);
X	return(NULL);
X}
X
Xstatic void resolve()				/* uses global lablst */
X/* write label links into the compiled-command space */
X{
X	register label		*lptr;
X	register sedcmd		*rptr, *trptr;
X
X	/* loop through the label table */
X	for(lptr = lablst; lptr < lab; lptr++)
X		if (lptr->address == NULL)	/* barf if not defined */
X		{
X			fprintf(stderr, ULABL, lptr->name);
X			quit(2);
X		}
X		else if (lptr->last)		/* if last is non-null */
X		{
X			rptr = lptr->last;		/* chase it */
X			while(trptr = rptr->u.link)	/* resolve refs */
X			{
X				rptr->u.link = lptr->address;
X				rptr = trptr;
X			}
X			rptr->u.link = lptr->address;
X		}
X}
X
Xstatic char *ycomp(ep, delim)
X/* compile a y (transliterate) command */
Xregister char	*ep;		/* where to compile to */
Xchar		delim;		/* end delimiter to look for */
X{
X	register char *tp, *sp;
X	register int c;
X
X	/* scan the 'from' section for invalid chars */
X	for(sp = tp = cp; *tp != delim; tp++)
X	{
X		if (*tp == '\\')
X			tp++;
X		if ((*tp == '\n') || (*tp == '\0'))
X			return(BAD);
X	}
X	tp++;		/* tp now points at first char of 'to' section */
X
X	/* now rescan the 'from' section */
X	while((c = *sp++ & 0x7F) != delim)
X	{
X		if (c == '\\' && *sp == 'n')
X		{
X			sp++;
X			c = '\n';
X		}
X		if ((ep[c] = *tp++) == '\\' && *tp == 'n')
X		{
X			ep[c] = '\n';
X			tp++;
X		}
X		if ((ep[c] == delim) || (ep[c] == '\0'))
X			return(BAD);
X	}
X
X	if (*tp != delim)	/* 'to', 'from' parts have unequal lengths */
X		return(BAD);
X
X	cp = ++tp;			/* point compile ptr past translit */
X
X	for(c = 0; c < 128; c++)	/* fill in self-map entries in table */
X		if (ep[c] == 0)
X			ep[c] = c;
X
X	return(ep + 0x80);	/* return first free location past table end */
X}
X
Xquit(n)
Xint n;
X{
X/* Flush buffers and exit. */
X  _cleanup();
X  exit(n);
X}
X
X/*+++++++++++++++*/
X
X/*
X   sedexec.c -- execute compiled form of stream editor commands
X
X   The single entry point of this module is the function execute(). It
X   may take a string argument (the name of a file to be used as text)  or
X   the argument NULL which tells it to filter standard input. It executes
X   the compiled commands in cmds[] on each line in turn.
X
X   The function command() does most of the work. Match() and advance()
X   are used for matching text against precompiled regular expressions and
X   dosub() does right-hand-side substitution.  Getline() does text input;
X   readout() and memcmp() are output and string-comparison utilities.  
X*/
X
X/* #include <stdio.h>	/* {f}puts, {f}printf, getc/putc, f{re}open, fclose */
Xextern FILE *fopen();
X/* #include <ctype.h>	/* for isprint(), isdigit(), toascii() macros */
X/* #include "sed.h"	/* command type structures & miscellaneous constants */
X
Xextern char	*strcpy();	/* used in dosub */
X
X/***** shared variables imported from the main ******/
X
X/* main data areas */
Xextern char	linebuf[];	/* current-line buffer */
Xextern sedcmd	cmds[];		/* hold compiled commands */
Xextern long	linenum[];	/* numeric-addresses table */
X
X/* miscellaneous shared variables */
Xextern int	nflag;	  /* -n option flag */
Xextern int	eargc;	  /* scratch copy of argument count */
Xextern char	**eargv;  /* scratch copy of argument list */
Xextern char	bits[];	  /* the bits table */
X
X/***** end of imported stuff *****/
X
X#define MAXHOLD	 MAXBUF		/* size of the hold space */
X#define GENSIZ	 MAXBUF		/* maximum genbuf size */
X
X#define TRUE	 1
X#define FALSE	 0
X
Xstatic char LTLMSG[]	= "sed: line too long\n";
X
Xstatic char	*spend;	 /* current end-of-line-buffer pointer */
Xstatic long	lnum = 0L;	/* current source line number */
X
X/* append buffer maintenance */
Xstatic sedcmd	*appends[MAXAPPENDS];	/* array of ptrs to a,i,c commands */
Xstatic sedcmd	**aptr = appends;	/* ptr to current append */
X
X/* genbuf and its pointers */
Xstatic char	genbuf[GENSIZ];
Xstatic char	*loc1;
Xstatic char	*loc2;
Xstatic char	*locs;
X
X/* command-logic flags */
Xstatic int	lastline;	       /* do-line flag */
Xstatic int	jump;		   /* jump to cmd's link address if set */
Xstatic int	delete;		 /* delete command flag */
X
X/* tagged-pattern tracking */
Xstatic char	*bracend[MAXTAGS];	/* tagged pattern start pointers */
Xstatic char	*brastart[MAXTAGS];	/* tagged pattern end pointers */
X
Xstatic int	anysub;		/* true if any s on current line succeeded */
X
X
Xvoid execute()
X/* execute the compiled commands in cmds[] */
X{
X	register char	*p1;		/* dummy copy ptrs */
X	register sedcmd	*ipc;		/* ptr to current command */
X	char		*execp;		/* ptr to source */
X	char		*getline();	/* input-getting functions */
X	void		command(), readout(), initget();
X
X
X	initget();
X
X	/* here's the main command-execution loop */
X	for(;;)
X	{
X
X		/* get next line to filter */
X		if ((execp = getline(linebuf)) == BAD)
X			return;
X		spend = execp;
X		anysub = FALSE;
X
X		/* loop through compiled commands, executing them */
X		for(ipc = cmds; ipc->command; )
X		{
X			if (!selected(ipc))
X			{
X				ipc++;
X				continue;
X			}
X			command(ipc);	/* execute the command pointed at */
X
X			if (delete)	/* if delete flag is set */
X				break;	/* don't exec rest of compiled cmds */
X
X			if (jump)	/* if jump set, follow cmd's link */
X			{
X				jump = FALSE;
X				if ((ipc = ipc->u.link) == 0)
X				{
X					ipc = cmds;
X					break;
X				}
X			}
X			else	    /* normal goto next command */
X				ipc++;
X		}
X		/* we've now done all modification commands on the line */
X
X		/* here's where the transformed line is output */
X		if (!nflag && !delete)
X		{
X			for(p1 = linebuf; p1 < spend; p1++)
X				putc(*p1, stdout);
X			putc('\n', stdout);
X		}
X
X		/* if we've been set up for append, emit the text from it */
X		if (aptr > appends)
X			readout();
X
X		delete = FALSE; /* clear delete flag; about to get next cmd */
X	}
X}
X
Xstatic int selected(ipc)
X/* is current command selected */
Xsedcmd	*ipc;
X{
X	register char	*p1 = ipc->addr1;	/* point p1 at first address */
X	register char	*p2 = ipc->addr2;	/*   and p2 at second */
X	int		c;
X	int		sel = TRUE;	/* select by default */
X
X	if (!p1)	/* No addresses: always selected */
X		;
X	else if (ipc->flags.inrange)
X	{
X		if (*p2 == CEND)
X			;
X		else if (*p2 == CLNUM)
X		{
X			c = p2[1]&CMASK;
X			if (lnum >= linenum[c])
X			{
X				ipc->flags.inrange = FALSE;
X				if (lnum > linenum[c])
X					sel = FALSE;
X			}
X		}
X		else if (match(p2, 0))
X			ipc->flags.inrange = FALSE;
X	}
X	else if (*p1 == CEND)
X	{
X		if (!lastline)
X			sel = FALSE;
X	}
X	else if (*p1 == CLNUM)
X	{
X		c = p1[1]&CMASK;
X		if (lnum != linenum[c])
X			sel = FALSE;
X		else if (p2)
X			ipc->flags.inrange = TRUE;
X	}
X	else if (match(p1, 0))
X	{
X		if (p2)
X			ipc->flags.inrange = TRUE;
X	}
X	else
X		sel = FALSE;
X
X	return ipc->flags.allbut ? !sel : sel;
X}
X
Xstatic int match(expbuf, gf)	/* uses genbuf */
X/* match RE at expbuf against linebuf; if gf set, copy linebuf from genbuf */
Xchar	*expbuf;
X{
X	register char	*p1, *p2, c;
X
X	if (gf)
X	{
X		if (*expbuf)
X			return(FALSE);
X		p1 = linebuf; p2 = genbuf;
X		while (*p1++ = *p2++);
X		locs = p1 = loc2;
X	}
X	else
X	{
X		p1 = linebuf;
X		locs = FALSE;
X	}
X
X	p2 = expbuf;
X	if (*p2++)
X	{
X		loc1 = p1;
X		if(*p2 == CCHR && p2[1] != *p1) /* 1st char is wrong */
X			return(FALSE);	  /*   so fail */
X		return(advance(p1, p2));	/* else try to match rest */
X	}
X
X	/* quick check for 1st character if it's literal */
X	if (*p2 == CCHR)
X	{
X		c = p2[1];	      /* pull out character to search for */
X		do {
X			if (*p1 != c)
X				continue;	/* scan the source string */
X			if (advance(p1, p2))	/* found it, match the rest */
X				return(loc1 = p1, 1);
X		} while
X			(*p1++);
X		return(FALSE);	  /* didn't find that first char */
X	}
X
X	/* else try for unanchored match of the pattern */
X	do {
X		if (advance(p1, p2))
X			return(loc1 = p1, 1);
X	} while
X		(*p1++);
X
X	/* if got here, didn't match either way */
X	return(FALSE);
X}
X
Xstatic int advance(lp, ep)
X/* attempt to advance match pointer by one pattern element */
Xregister char	*lp;	    /* source (linebuf) ptr */
Xregister char	*ep;	    /* regular expression element ptr */
X{
X	register char	*curlp;	 /* save ptr for closures */ 
X	char	    c;	      /* scratch character holder */
X	char	    *bbeg;
X	int	     ct;
X
X	for (;;)
X		switch (*ep++)
X		{
X		case CCHR:	      /* literal character */
X			if (*ep++ == *lp++)	/* if chars are equal */
X				continue;	/* matched */
X			return(FALSE);	  /* else return false */
X
X		case CDOT:	      /* anything but newline */
X			if (*lp++)	      /* first NUL is at EOL */
X				continue;	/* keep going if didn't find */
X			return(FALSE);	  /* else return false */
X
X		case CNL:	       /* start-of-line */
X		case CDOL:	      /* end-of-line */
X			if (*lp == 0)	   /* found that first NUL? */
X				continue;	/* yes, keep going */
X			return(FALSE);	  /* else return false */
X
X		case CEOF:	      /* end-of-address mark */
X			loc2 = lp;	      /* set second loc */
X			return(TRUE);	   /* return true */
X
X		case CCL:	       /* a closure */
X			c = *lp++ & 0177;
X			if (ep[c>>3] & bits[c & 07])	/* is char in set? */
X			{
X				ep += 16;	/* then skip rest of bitmask */
X				continue;	/*   and keep going */
X			}
X			return(FALSE);	  /* else return false */
X
X		case CBRA:	      /* start of tagged pattern */
X			brastart[*ep++] = lp;	/* mark it */
X			continue;	       /* and go */
X
X		case CKET:	      /* end of tagged pattern */
X			bracend[*ep++] = lp;	/* mark it */
X			continue;	       /* and go */
X
X		case CBACK: 
X			bbeg = brastart[*ep];
X			ct = bracend[*ep++] - bbeg;
X
X			if (memcmp(bbeg, lp, ct))
X			{
X				lp += ct;
X				continue;
X			}
X			return(FALSE);
X
X		case CBACK|STAR:
X			bbeg = brastart[*ep];
X			ct = bracend[*ep++] - bbeg;
X			curlp = lp;
X			while(memcmp(bbeg, lp, ct))
X				lp += ct;
X
X			while(lp >= curlp)
X			{
X				if (advance(lp, ep))
X					return(TRUE);
X				lp -= ct;
X			}
X			return(FALSE);
X
X
X		case CDOT|STAR:	 /* match .* */
X			curlp = lp;	     /* save closure start loc */
X			while (*lp++);	  /* match anything */ 
X			goto star;	      /* now look for followers */
X
X		case CCHR|STAR:	 /* match <literal char>* */
X			curlp = lp;	     /* save closure start loc */
X			while (*lp++ == *ep);	/* match many of that char */
X			ep++;		   /* to start of next element */
X			goto star;	      /* match it and followers */
X
X		case CCL|STAR:	  /* match [...]* */
X			curlp = lp;	     /* save closure start loc */
X			do {
X				c = *lp++ & 0x7F;	/* match any in set */
X			} while
X				(ep[c>>3] & bits[c & 07]);
X			ep += 16;	       /* skip past the set */
X			goto star;	      /* match followers */
X
X		star:	   /* the recursion part of a * or + match */
X			if (--lp == curlp)	/* 0 matches */
X				continue;
X
X			if (*ep == CCHR)
X			{
X				c = ep[1];
X				do {
X					if (*lp != c)
X						continue;
X					if (advance(lp, ep))
X						return(TRUE);
X				} while
X					(lp-- > curlp);
X				return(FALSE);
X			}
X
X			if (*ep == CBACK)
X			{
X				c = *(brastart[ep[1]]);
X				do {
X					if (*lp != c)
X						continue;
X					if (advance(lp, ep))
X						return(TRUE);
X				} while
X					(lp-- > curlp);
X				return(FALSE);
X			}
X	
X			do {
X				if (lp == locs)
X					break;
X				if (advance(lp, ep))
X					return(TRUE);
X			} while
X				(lp-- > curlp);
X			return(FALSE);
X
X		default:
X			fprintf(stderr, "sed: RE error, %o\n", *--ep);
X		}
X}
X
Xstatic int substitute(ipc)
X/* perform s command */
Xsedcmd	*ipc;			   /* ptr to s command struct */
X{
X	void dosub();		   /* for if we find a match */
X
X	if (match(ipc->u.lhs, 0))	       /* if no match */
X		dosub(ipc->rhs);		/* perform it once */
X	else
X		return(FALSE);		  /* command fails */
X
X	if (ipc->flags.global)		  /* if global flag enabled */
X		while(*loc2)		    /* cycle through possibles */
X			if (match(ipc->u.lhs, 1))	/* found another */
X				dosub(ipc->rhs);	/* so substitute */
X			else			    /* otherwise, */
X				break;		  /* we're done */
X	return(TRUE);			   /* we succeeded */
X}
X
Xstatic void dosub(rhsbuf)	       /* uses linebuf, genbuf, spend */
X/* generate substituted right-hand side (of s command) */
Xchar	*rhsbuf;	/* where to put the result */
X{
X	register char	*lp, *sp, *rp;
X	int	     c;
X	char	    *place();
X
X	/* copy linebuf to genbuf up to location  1 */
X	lp = linebuf; sp = genbuf;
X	while (lp < loc1) *sp++ = *lp++;
X
X	for (rp = rhsbuf; c = *rp++; )
X	{
X		if (c == '&')
X		{
X			sp = place(sp, loc1, loc2);
X			continue;
X		}
X		else if (c & 0200 && (c &= 0177) >= '1' && c < MAXTAGS+'1')
X		{
X			sp = place(sp, brastart[c-'1'], bracend[c-'1']);
X			continue;
X		}
X		*sp++ = c & 0177;
X		if (sp >= genbuf + MAXBUF)
X			fprintf(stderr, LTLMSG);
X	}
X	lp = loc2;
X	loc2 = sp - genbuf + linebuf;
X	while (*sp++ = *lp++)
X		if (sp >= genbuf + MAXBUF)
X			fprintf(stderr, LTLMSG);
X	lp = linebuf; sp = genbuf;
X	while (*lp++ = *sp++);
X	spend = lp-1;
X}
X
Xstatic char *place(asp, al1, al2)	       /* uses genbuf */
X/* place chars at *al1...*(al1 - 1) at asp... in genbuf[] */
Xregister char	*asp, *al1, *al2;
X{
X	while (al1 < al2)
X	{
X		*asp++ = *al1++;
X		if (asp >= genbuf + MAXBUF)
X			fprintf(stderr, LTLMSG);
X	}
X	return(asp);
X}
X
Xstatic void listto(p1, fp)
X/* write a hex dump expansion of *p1... to fp */
Xregister char	*p1;	    /* the source */
XFILE	    *fp;	    /* output stream to write to */
X{
X	p1--;
X	while(*p1++)
X		if (isprint(*p1))
X			putc(*p1, fp);	  /* pass it through */
X		else
X		{
X			putc('\\', fp);	       /* emit a backslash */
X			switch(*p1)
X			{
X			case '\b':	putc('b', fp); break;	/* BS */
X			case '\t':	putc('t', fp); break;	/* TAB */
X			case '\n':	putc('n', fp); break;	/* NL */
X			case '\r':	putc('r', fp); break;	/* CR */
X			case '\33':	putc('e', fp); break;	/* ESC */
X			default:	fprintf(fp, "%02x", *p1 & 0xFF);
X			}
X		}
X	putc('\n', fp);
X}
X
Xstatic void truncated(h) int h;
X{
X	static long last = 0L;
X
X	if (lnum == last) return;
X	last= lnum;
X
X	fprintf(stderr, "sed: ");
X	fprintf(stderr, h ? "hold space" : "line %D", lnum);
X	fprintf(stderr, " truncated to %d characters\n", MAXBUF);
X}
X
Xstatic void command(ipc)
X/* execute compiled command pointed at by ipc */
Xsedcmd	*ipc;
X{
X	static char	holdsp[MAXHOLD+1];	/* the hold space */
X	static char	*hspend = holdsp;	/* hold space end pointer */
X	register char	*p1, *p2;
X	char		*execp;
X	int		didsub;		/* true if last s succeeded */
X
X	switch(ipc->command)
X	{
X	case ACMD:	      /* append */
X		*aptr++ = ipc;
X		if (aptr >= appends + MAXAPPENDS)
X			fprintf(stderr,
X				"sed: too many appends after line %D\n",
X				lnum);
X		*aptr = 0;
X		break;
X
X	case CCMD:	      /* change pattern space */
X		delete = TRUE;
X		if (!ipc->flags.inrange || lastline)
X			printf("%s\n", ipc->u.lhs);	     
X		break;
X
X	case DCMD:	      /* delete pattern space */
X		delete++;
X		break;
X
X	case CDCMD:	     /* delete a line in hold space */
X		p1 = p2 = linebuf;
X		while(*p1 != '\n')
X			if (delete = (*p1++ == 0))
X				return;
X		p1++;
X		while(*p2++ = *p1++) continue;
X		spend = p2-1;
X		jump++;
X		break;
X
X	case EQCMD:	     /* show current line number */
X		fprintf(stdout, "%D\n", lnum);
X		break;
X
X	case GCMD:	      /* copy hold space to pattern space */
X		p1 = linebuf;	p2 = holdsp;	while(*p1++ = *p2++);
X		spend = p1-1;
X		break;
X
X	case CGCMD:	     /* append hold space to pattern space */
X		*spend++ = '\n';
X		p1 = spend;	p2 = holdsp;
X		do
X			if (p1 > linebuf + MAXBUF) {
X				truncated();
X				p1[-1] = 0;
X				break;
X			}
X		while(*p1++ = *p2++);
X
X		spend = p1-1;
X		break;
X
X	case HCMD:	      /* copy pattern space to hold space */
X		p1 = holdsp;	p2 = linebuf;	while(*p1++ = *p2++);
X		hspend = p1-1;
X		break;
X
X	case CHCMD:	     /* append pattern space to hold space */
X		*hspend++ = '\n';
X		p1 = hspend;	p2 = linebuf;
X		do
X			if (p1 > holdsp + MAXBUF) {
X				truncated();
X				p1[-1] = 0;
X				break;
X			}
X		while(*p1++ = *p2++);
X
X		hspend = p1-1;
X		break;
X
X	case ICMD:	      /* insert text */
X		printf("%s\n", ipc->u.lhs);
X		break;
X
X	case BCMD:	      /* branch to label */
X		jump = TRUE;
X		break;
X
X	case LCMD:	      /* list text */
X		listto(linebuf, (ipc->fout != NULL)?ipc->fout:stdout); break;
X
X	case NCMD:	/* read next line into pattern space */
X		if (!nflag)
X			puts(linebuf);	/* flush out the current line */
X		if (aptr > appends)
X			readout();	/* do pending a, r commands */
X		if ((execp = getline(linebuf)) == BAD)
X		{
X			delete = TRUE;
X			break;
X		}
X		spend = execp;
X		anysub = FALSE;
X		break;
X
X	case CNCMD:	/* append next line to pattern space */
X		if (aptr > appends)
X			readout();
X		*spend++ = '\n';
X		if ((execp = getline(spend)) == BAD)
X		{
X			*--spend = 0;
X			break;
X		}
X		spend = execp;
X		anysub = FALSE;
X		break;
X
X	case PCMD:	      /* print pattern space */
X		puts(linebuf);
X		break;
X
X	case CPCMD:	     /* print one line from pattern space */
X		cpcom:	  /* so s command can jump here */
X		for(p1 = linebuf; *p1 != '\n' && *p1 != '\0'; )
X			putc(*p1++, stdout);
X		putc('\n', stdout);
X		break;
X
X	case QCMD:	      /* quit the stream editor */
X		if (!nflag)
X			puts(linebuf);	/* flush out the current line */
X		if (aptr > appends)
X			readout();	/* do any pending a and r commands */
X		quit(0);
X
X	case RCMD:	      /* read a file into the stream */
X		*aptr++ = ipc;
X		if (aptr >= appends + MAXAPPENDS)
X			fprintf(stderr,
X				"sed: too many reads after line %D\n",
X				lnum);
X		*aptr = 0;
X		break;
X
X	case SCMD:	      /* substitute RE */
X		didsub = substitute(ipc);
X		if (didsub)
X			anysub = TRUE;
X		if (ipc->flags.print && didsub)
X			if (ipc->flags.print == TRUE)
X				puts(linebuf);
X			else
X				goto cpcom;
X		if (didsub && ipc->fout)
X			fprintf(ipc->fout, "%s\n", linebuf);
X		break;
X
X	case TCMD:	      /* branch on any s successful */
X	case CTCMD:	     /* branch on any s failed */
X		if (anysub == (ipc->command == CTCMD))
X			break;	  /* no branch if any s failed, else */
X		anysub = FALSE;
X		jump = TRUE;	    /*	set up to jump to assoc'd label */
X		break;
X
X	case CWCMD:	     /* write one line from pattern space */
X		for(p1 = linebuf; *p1 != '\n' && *p1 != '\0'; )
X			putc(*p1++, ipc->fout);
X		putc('\n', ipc->fout);
X		break;
X
X	case WCMD:	      /* write pattern space to file */
X		fprintf(ipc->fout, "%s\n", linebuf);
X		break;
X
X	case XCMD:	      /* exchange pattern and hold spaces */
X		p1 = linebuf;	p2 = genbuf;	while(*p2++ = *p1++) continue;
X		p1 = holdsp;	p2 = linebuf;	while(*p2++ = *p1++) continue;
X		spend = p2 - 1;
X		p1 = genbuf;	p2 = holdsp;	while(*p2++ = *p1++) continue;
X		hspend = p2 - 1;
X		break;
X
X	case YCMD:
X		p1 = linebuf;	p2 = ipc->u.lhs;
X		while(*p1 = p2[*p1])
X			p1++;
X		break;
X	}
X}
X
Xstatic void openfile(file) char *file;
X/* Replace stdin by given file */
X{
X	if (freopen(file, "r", stdin)==NULL) {
X		fprintf(stderr, "sed: can't open %s\n", file);
X		quit(1);
X	}
X}
X
Xstatic int c;	/* Will be the next char to read, a kind of lookahead */
X
Xstatic void get()
X/* Read next character into c treating all argument files as run through cat */
X{
X	while ((c=getchar())==EOF && --eargc>=0)
X		openfile(*eargv++);
X}
X
Xstatic void initget()
X/* Initialise character input */
X{
X	if (--eargc>=0) openfile(*eargv++);	/* else input == stdin */
X	get();
X}
X
Xstatic char *getline(buf)
X/* get next line of text to be edited, return pointer to end */
Xregister char	*buf;	   /* where to send the input */
X{
X	if (c==EOF) return BAD;
X
X	lnum++;		/* we can read a new line */
X
X	do {
X		if (c=='\n') { get(); break; }
X		if (buf <= linebuf+MAXBUF) *buf++ = c;
X		get();
X	} while (c!=EOF);
X
X	if (c==EOF) lastline= TRUE;
X
X	if (buf > linebuf+MAXBUF) { truncated(); --buf; }
X
X	*buf = 0;
X	return buf;
X}
X
Xstatic int memcmp(a, b, count)
X/* return TRUE if *a... == *b... for count chars, FALSE otherwise */
Xregister char	*a, *b;
X{
X	while(count--)		  /* look at count characters */
X		if (*a++ != *b++)	/* if any are nonequal	 */
X			return(FALSE);	/*    return FALSE for false */
X	return(TRUE);		   /* compare succeeded */
X}
X
Xstatic void readout()
X/* write file indicated by r command to output */
X{
X	register int	t;	/* hold input char or EOF */
X	FILE	    *fi;    /* ptr to file to be read */
X
X	aptr = appends - 1;	/* arrange for pre-increment to work right */
X	while(*++aptr)
X		if ((*aptr)->command == ACMD)	   /* process "a" cmd */
X			printf("%s\n", (*aptr)->u.lhs);
X		else				    /* process "r" cmd */
X		{
X			if ((fi = fopen((*aptr)->u.lhs, "r")) == NULL) {
X				fprintf(stderr, "sed: can't open %s\n",
X					(*aptr)->u.lhs);
X				continue;
X			}
X			while((t = getc(fi)) != EOF)
X				putc((char) t, stdout);
X			fclose(fi);
X		}
X	aptr = appends;	 /* reset the append ptr */
X	*aptr = 0;
X}
X
X/* sedexec.c ends here */
X
END_OF_FILE
if test 45843 -ne `wc -c <'sed.c'`; then
    echo shar: \"'sed.c'\" unpacked with wrong size!
fi
# end of 'sed.c'
fi
echo shar: End of shell archive.
exit 0
-------------------------------------------------------------------------------
-- 
Earl Chew, Dept of Computer Science, Monash University, Australia 3168
ARPA: cechew%bruce.cs.monash.oz.au@uunet.uu.net  ACS : cechew@bruce.oz
----------------------------------------------------------------------