35-DISK DOC 36-DISK DZC~ARGS C CAT CZ \CC CZMzCC DZF -CC DZC+CC1 CZ CC11 CZ CC12 CZ , `CC13 CZ LCC2 CZ hWCC21 CZ n!CC22 CZ 8CC3 CZ `CC31 CZ (CC32 CZ CC33 CZ ײCC4 CZ QCC41 CZ yCC42 CZ gCCC SUB)JCCCC SUB*CCCM SUB,CCCR SUB-}CCM SUB.CCRTL MZC/_VCCRTL RZLDELBR CZM>սLU CZMh|wSCLIB1 LBRL8SCLIB2 LBRo,vUW CZ |WC CZ  ; *******Disk K35 -- Small C (Version 2.1) Compiler & Source****** Disk 35 is Fred Scacchitti's upgrade of the Small C compiler (Version 2.1) and includes source. He's incorporated Jim Hendrix's additions and added a few of his own tricks -- global initialization option, no boot option, conditional operator, 4K file buffers for input, output, and includes files, and many more. Read CC.DOC for all the details. This version requires Microsoft's M80/L80. ***************************************************************** v36-DISK.DOC[04/07/91]% AB$@W2 fi@T7@Khm0 M(IRL &LG# T+Fqi7i6 a`5 Sqi7itU)!7A he2)BQ $MKOLHdrY9 Å1|F9^3 h4," g7g- o9:D#yciXPzƓe@bM- 6μzamp}Gb,.rp:=4:n',EL7Z򲉬r h@+±@; #>C9`:#80"Ҧa /c;cB7'"<#('P;on4@!H`"p&Ie)J>) -, ȈOc26o$& main(argc,argv) int argc,*argv; { int count; count = 1; /* One line does it all*/ while(count != argc) prntf("\n argument = %2d , argv = %d , *argv = %d , string = %s ", count++,argv++,*argv,*argv); prntf("\n"); /* makes it look neat */ } vCAT.C [04/07/91]% @PT 1N$i6D3yt2r7Fh$b< 1Rqr/ つ 'B4FiHt2GƁ<R: ճpd7NL #) SPci(01f v,B F;ˣ H&a c,^`F㡘P".F!g2[S5cq/'he!D)FSQfϽQeǶCy7Ė%`ŏ|0f*&x@n(n=Ԓ3B; P{0#2PV SCc06 Z-:E1Z#hŦ# PIC;P3A#t xKoX60:/l&P2[Cr?LP3t: rʤa "33 eG(FwGDhvCC.COM[04/07/91]% `)lM/2Np耀f Ph(7@ȈB"#DP +h 4  `g2@6óJ@,i `W@ ? H>e;k+j0$÷@`rL)g!1-EYd Cx|:qZW?O!5(mKvt:? $@M'IP4:}NVh5q.脡f@mj|\2 Z! b k3@al"i@"@B0z!a 1C"ތb0: J (@)TA-K, RlF d&b7dJQ!Ҋ/pIIa{8qM'l?1  C|t2ZZ)|elaibJd&L)) 2 u~p@pha WX  &٥xh&]@E>K\72p|y,w!sF<j.IJa 3@ =%P]{ֺZnmջVV~ba AC, 4MI{Qʹ:ψ @0!Iq݈n 6Xsru Do-?k]XaLxo_aN$dE$UH:08IYMp>a$q+!VOCJ҃f(#u uTQd0f} "|$@r5FY*(͓J ` `%`.N/ppG(PiA7~`?Ӝct?f2GSRA0<"n>pB9tSA#h@@҂Vꨊjӂc-ټDV:bDJ/8y4&co7#xo1tGej!~),S3h0dɪS(Z( @*U(ھ,Op@EN!eMDv΋M C<'V 'ќ80N<@R541W_|Vf`8 (۴A QG#(K[@Uz#(b"=FhNx=@"K ޽*0> yπX1uMe :ڋDTǀ ?( P :H9 P!0rex?;/Xad(<p::H164p1`: 2p7A0b@(4(h93+29k*3Bfh`ah6Xu=(,xl($( 9h3/Ah4C4PqhLaPa~(>X.hab}hzp,0xZ)DxCapG$"בKGDMhZ2dq"A7785(: ;27`ۃIЧ |@ă{TD ~HP{>vSC3#S1l`x'([RXf#CهI[ fpXkɳ3%p`9Ƀ$FCq4l%q0LR[ɨDKH4XDDK@HK$K3I4K4,4K-i6\hsx&4x kvx(Cx$Hx'Mx' $:3(<01-p%-h0܁h4`8lt僀.|h97䌁SH4V(jF e3߾ \P\}sY=q\Qu1\4a hWHp@h\ heJ]ݳ&m?e|H@ Y`T\4`߸i]p:  m) H&`22!ل" $0Ef^)^X2;C )}hc=ӵiw a؁@HHF'A,/xlZ*c4 ۄy[zn)c!ɲ+Nc,ĀV ]x n2`+j$V`%&žY/ a`Xa@  j p8q(aaŽnVָϫEX\`Zj$ag6V(/2>"jdBkfhdD"M=cv.hh j؞IkVՍPm W3 o Άn²Am3kMhޒ=σ>-Ge7YQ9@<1oFouԈ<| j $n^ }fopx!&Goht A`lAP3;σ!xq06C8cdhRgpHKIgy~Ҧ^cuqPMS`cXohIѹ>g^2` O47(\m` ;_#o+wtAm5A䵽2xg,j@ZAPZv:r'1Pj4)ot2`Wt(a_s)unvhty?VuhaOA'S2fDWMu}ueLYX?uvqdYƭ/h: [~h+4 |u)#@'FҞ܃(8^i)6{c H9-O03 sHTJ= O08Dχ35p+&cSC5jSB\PTHd-~̨384[*h3 h4:d|h4{d ǘ257 KDz=Aa=cNkzp9(67 f`D3UVwE8Y8Xp+9v<,xaUX,aj:c7/uB60azw0 +3;;YsۥIpgz2tagu&J$H*z8f X,G@aa_][myV[νl~l2`w@r-Hs%qyFl2`9۰|V=he5y>UH!Pgl=&p>߾XZiPC;2JTHsc\Jg3@ќh~p{zA G\kQyͫA(٤2 rJMdDHy5siG ,oR>q#궢'uahiG^|s(iOcnRvف̪咦A^wHdwaG*)O H l?Y3dk0q#gd~kf'xslF3[08=t^S]#J89]!D^#5p* q( KEJᬸ޷Zk`jHy$k`}-E2@4#4Y,=R/Nh;BX'Di9̴[,#JT2`0JI45&0H8Խs"~'#@햱;Uhd=8[ NRh;Q0 5 ڦ(ĿBMhhVL#<.n+8&u8?,9mdH8܃<=h4Wx80a흻.8~ho91YB?,޴ub[F|znK06o'GՅd[Pl`z['@e\0M&Mxاl;~t`b[lד&BkHuFm'MvtWw2jɃ27GbγL3;)6uEBώAv5t2tC:MC;2,^eH6g禓",=_Sp5lxXOKcs>ax+4E 9 H`2*qfh\`5`g24IB6*8DQhQ 9h(aflHfo_qC<>kÉb ]vd96itM+D[)Hj|}Fw9!X Wޒ{oMaT5LTx (CN[s&7Uwnjs:fK7TC6ݶ(>_2`UV>3āH=%e7ZYs&xS'l8x[{:}XPddLU iA{:s9[᭕uxX4Zy'11IxaK&2q2w본}o륒Pv'%GqXè0yh?'d!%l7e`fذfOP-aqM庅zܹf\HPl?-e:,woB !-9Yx ץ17^ T7 Hz89X}E\1v8dH.U qGM8<;b2 ^rJZ 6&Ϻ7"0=|GH7`0||68 jI&:#Q>׏8P^83`g[&l>D_&Z oWXaXW]W&XTJ` >[ΰo>9c8k& zÝfo먘o*(ePd=S)5F&}Goug;B֫Ǖ+zL[z˚l̘8al$<s"$ F %?|N2`-,&&`0 7|n1C[P?wanf(e0 `q88POifP&L*i5i2Ci7B24R`|GN[8 GPP#XX88&fPNLZS7 )cd{=is< sPE #8s n` MJHCfh@`G5 yT:v:ZDI8_i`I6z [(eZ; yNk۽[Jrax,<8l44@43Ń(3@2fŃH3Heh?D]eM1w9,_3fM8M0c7䌆o<&Ne,hD{&x&8YIRdW} Ӷ羐ˢiQT`(['IJČL 2`'a^fX,d{a:SuZno%څ>mAgS' XS6ʚFO.C=I~P|S~kef a" 2κP [U835댶|V`-Uf5pH{G[>H>p0TŪhu.^:/`5^=C 2՟h^s:4mϴPa[(q9HT8vkÊ[Q+ Hۘf QvvM]A_N,?CHf,UӺCCs&!ͪ;WamIPnW8 AɇycUq8͓ň9YXv~6y\d0:SG:03{p7=E۝,^fhj,(fa=Kξ%I8E=bbMy$&= Ej*7"L8{&tˇer}+`Ԇ0;w,}7$2`44L~|y`Y#` Љ7Ex*@q<3ˤ2A1=x`wEɾX3kZbE6TU`dzPH#$C<pԝ2` ҟvp2`KOXko3{dHPKľwo#&BqɄdH> 2tK8HK2KEQBj]$ܺDCPkK\"_|Z:̀4fW^usaknP\CP(fhacם`: `;2S&AA_ah_+vΒ5A2`oQAJb[ö 6k c?pIO22a`v#=ȢP&<_eA[haHtYsC9cPRC8>kYkIi3R-af`=A!3VqkpjE %gU抰P;qaf9;(Qn\ ȍ7n^l2E፟S)ְ9*C^QEQ#*[z6Xjz)@6`lHP,>X{22`{aa)UqOsՖD>j`!%|g1ؒVg me*_3 kW4FC JR>ꀉ˺! ,/u> 8f,ۍ5nۍAuYs"&X.k@IZ05WlUw*-~f+8fn'$:scV+&8!, 䔲`fh 1u5V5Gv)mBd-_X*tŭ,9vxd*FR<([aȉ²kvb2\6}},"h'>('LTTdRc=|[A^$"*"=_mGte#(mGYKm̆+FW {(E".I3P)1j(qKӵ1ַx"o "VU "̂-KZ[!ecf1a[a.(H"~h5QQ??O".C7ܥ" 4x4|=K0gm$τ$ [l|XK0Ő$(φ`$ 4XmHU3a$k[ u$ql/llҀ}l}({[Fš*:donq(l2f;y]|nL,>7j#@y#}c)h47b S4mQ8>ુC4v3N4pnzHCl.0h gd52#]꥾gdC2oQ&*`]3㲘`Zngdኸo73t [zO""8&sݜW]s)},@ gdXIm$P g>8 @(p+&&)m& vCx4:+ECsPfk0M;IpH+DНo| v@ziGRlhwe0L MJ )ˏhl?BFf]Ա@[:H|ޤa ]8N&H' &˧\|P kIՁ'{a^#5A܎u"VC2`l|Su:x`QI sDRWpSYv|nf.왲XIĦfC@(~{52`?808Da$4+g2`C8Q)18,C4J爳BlXɐ? I&窈M 2[nr8@2E]Qw0WM0qԚ'ܷ*M:G)+&X))Q8(J.v"?D\%aP m2`58 _I8s:\e^#5,ƌdm*#5l')G%[.Ios&P)qY'PF&?ʏI:>jW!1h.?$\%:2c.>uV.^&]ԍBv]Ta)\.5RgQwʕ %T8ʵJϡR/[Ҥ2wCk1k4Pa碚gQ=&\6ċ^Ũ( m <0p91H8GiN'x`t.0*M#+/ N0Kr*;~v:*kԗ8f+JH1-"AR]8H*k1bRR8^\6eӯE^SF_ɢY1ns:7 ܙ`4]*CLLAڰ5%.'ufGj#5 ~[@+lo*X`~'+y~zLIS@x8[nr%0$1-Wu-`LP+α8]wP;a+_ 18J`r"32,$=P\ ]I€I^wB6eeX+/hAap+˸2 (7u>''!)8!b[ᯕc&30&r)u8eq⿗ ,[>4E) +s:)14(14ʬ2`8}A`3,(1Hx>L5@,lnRd1Ί(K4a<Ƀ:+,oڭl賬2``1Xᄆd_JlIJԮC&,j P,K-hiu2`P-莸`$ȩ`-/ }5au ` PP@p- ,YBa+&,N7Q<30s&P-vOpkRkAfhOSnk-4ƅda8-PfhbxkzlW*'JjG-kveM0fh ;JiJ:m{:9jGOJR:llbJX_Y9mDvJcꎪYh9ˬ 5!\kfh(ӛ^ B<]P;uh:H*d,-z:__Md]N hNuZ;p`En_okw HvMO<|hXx46Se<gW}4)S72`-feOT‚ACc0Adf8?(:rAd ÁPea MԜ nR6 G8"7 5/-7rӶCH3U :$2`' *rd0C&P0%%C/DI),UƀH*(,)s$~x 賬mȘƞ0^X`ie d#$df8$p*h<|hmpPrJUUt^,rmdW&d@2!T ;6P3WC]-nmԭP+#& yrn-vfaC $ a2qhMO!""ꊸo ,8Hd'Kv ,Li }"d)$h82Ho `&2EH)(*Rd*LQ4~ASRd&.h5/I9ØH5/Ol|`Snr865΋$BckZ?Xf8_"xfR L tQnrx6T2wkZ?=X8\+PƎI5|Wh(5 tO6ԉKHx6({kZ?h]p,O  I`6(o6,Or0 nrXp,OrD;(3PE8`/w>@2G 6E`6(EGFeP@2G!}xa`6(lPGP^w x,Oi({Z?u2G !(:{Z? h72g8.r(7LLJ72G (x{Z?x=/Lxe8a8x_8Y="`=x+ H<x#z_! YJ؋8dp'#<$$t]84Hu| 8>727(8ta~?x3O7"@3xdrאpdk@.{){4y4b >7Y9\pP3 QQ8dP9@OL`9O@lXdhXdlXdw3a9^Xf9Hf XdXkdhkXd^o6S7N8dhw d8>x7K9pQ8dO0dXV !I XdlXd o|chkHf@Xkf \l ' r=D $7vK5rO9^o-XOӐkvCC.DEF[04/07/91]% ABTT*ͦaZCӁe9 ѣn " g4d % Y n2L@o2LƓ)@vH$F#Ȁ. f3 h4^7iT(p3&C)@a9D!7 sMx 7) 66.e/f{,ghwC :X#6al s15 ]>$ :<2wGXp8eFΆ \D'-ҹ`6J"ܞP`cg |F:7(7 ,=H!I lXPjጣ :*:OƐ; cA#B˪ è1I9SEaPKַ0XH! EhBR8@T9#h0RhˠL 0Բ8`2)8/-; 0ͨ2K7@ <<9 C2C`)J6@ 7;hL*+&D:!2p[н{U چtp;4HNɠH@98p_p0-RB6*z8#J2=.*3 w}XbXe= =@ ^ ϸؚ?b \ҡ #b Wr@.T}e_x=; -vHU ¨& !ծ&:`+ 2.^#POl<RQ |Bh?R : h#TG/%l tlB o 9prܚ,ɯy7f#45t zh*}`vR9kүNm=QTr&&$.zBv"Fw~P6rԯMF̛f @w ҍ;jCV ڣ7</ I $!e\˪~e40_Ze*- ȁ.$=  %w7s;M5 :r0w W(#!uִiA`:DI9BY?E@"BhIi48TdF j|r]A@eRp#9/جI&fbzve)f fd 3P{K_gY;\ v'*,Tz/IgòcXPvt|I!>m_r~p+d{tGu3322A'`a#sUBx spD,I:0_H-!_+E#)`*@$1R`^&Hbr+`Sx($-@숩 +Ț.lp)8?A\"?Љ@>?$?(@ =rȽ ؆pB,:s'rt$?a X Cã8 c* -* 4Ax+4ƸD("#1(6!@&J|Tr&TG$'7H'Y"-S(# 0>#?(da@E;XEqr82dNG%ǛrHGP*(1v T]+hp)'2} ir𮐿TT?&>Y:Ŭ[LQUBzIp*Eĸ,l%A&#iH0Gx#4Iawa X$A#ʐĦA,+9; 4\,K@Ti<?n oD'&` ɜD KEQKP"p"L\DƓHDLT(#L8&I L;MLL\LM0)hL` TӂԄ4t0TLX)$ρM/&ah! ,].vCC.DOC[04/07/91]% ABPm0 h  3n:Ny  SVKbj:m8űsj9 6(9 80m!Ct y,(7G+ ٶ"3 !O'Pt\9!HB#89;q6p"196r$ "Cv6 #,+<"  Cf!Hz"޵ SXarK0Llq D<Ž #; Xč 9 m4c0!Ʊ\'MFL{ڈ61b=:<󥁀f @8)X3c Oʵ%OATBЎ}NC)7cg1xOl8ٸˆ"bx- < XVCx7ã]G^&, #]263OڻhDﰯ3Zs* P:#L4@1)C7039 ,)L3tfhL#p6'S`FsjHN) ι>O׺!$)Fs4Up6]u6ZɽgG4pš1Ҵ-K:|^;\7\'L2kĬ0͐#6 # a`j&Y&L2i,a/=Sy>[b?@QZ㢠>fтLpd5fU `j eM!\IkGa)C0;6":[;3yqdTr AQ{&9CG`@ 88 zya l^ʘo D-'ǬC%12' wxlaCXnC `*B} gdugs1d6#q:ZĘ#P@(x~$/@SJ /`56é='"YxuDCRH8$U0؉)B&fLpFBT H"9pH!8!PBpT i*IÙC !!RJlJQC6MBPuOF`0åQTF C fH\^Yv=e[ *ӣ븅ėT81P`0M?דF(iu# YCePѹJ"l碏iD& )q@{ .2:zü ̏z 4e uH%OYDLvTCKK$ӻ/̊8ʆpB!`)d|Iy 1~'FL LމHĀLucfZD]Tؖ <+%RN_=Ħ'r(?[&x! 22 WuOMڇEd"KYeƮfP1 dB; )L,H" @hDpxoܢF[ʳpxɫ rG$d} p2CJ8nE*d`n1шRdeUf)zie17)r@rL(DfP깕)|V;Uha 92=f(=(b*0eyh ʶReƆ3TE/ntrtq#]tWqXF)xVYV}| 2ON=<؏]/ 7*`b-_۸4؞8tƐc)frp"M{26$\,sCSY I8|m$8/dnVs4U*4ei"RQճruE^m\Tkpз'lYd@hBd6wXk0hw:@U/txJlLj6| O9'@sBP`uSMBu >skw] IwO7.<a h qϵ=f*/5#fgI1 ,=t7A?*MOv"k_-<хtaXr N6duJt#ncfd4Z.޵n.a5(l3Lwڵfy?멭ZחyМCͬ9o(ۙ[ ?h!3٭ +$"ɯY !0i r>(B9x߸,B+!C *'Xh ۆQTa)+ʰlZÍRIX>#$G&"3q&X- +>ٴٓM#H :1-ԾP0Tۗ+(e.x7 @ ȣ|C> (&൅ (Ԡ:qDBk:RS¯s ڜQCC5 蕋9*, _ؚPEW@RsEEKǻ@Hїl@X t79Ƅ9:#,hd򑙼h-4<Y˃X6ڻ;E;;X ;͊IL9 긗|>5D ALCs=@Yd=z0H,PՕ~2_JƏэ ˃8$Z$!$C$V%R89%JU W9 ׏[:0807(̐(ya2!9[h:84bX2+S@);襃,c 6cଢ଼1ʻ5*A [cE-Q i66ơ ૯H6HLEHʸJM1a:3`;.@ 1.hګ#`Q?já 5|E𤌂<(rEL@ _يd%Y2$[B&%_&aMbcM 1JLL>XJM:j:Gi37ªJ$nفwۜ2QГH&z x'98!S ѝqɡ2I/ꤎ+4ɝ%KT?hMMԴ 04\'w6ɫx.N,1q7 &-8ӂ}B(0+!Oys&+Y=橔 :\S11K\_ ʂ_:kLh,Gɗt`79(tS")) X69 gG膻 .&]Fo ppقi/÷CCӗ(qR+"Xs8KÕRո`>F3ΰوРBˏP7?yiÐTJ*d.BȈFFWU {HH̶ u?M8<[ee ,HxҵfI:ϴy ]‰A"u*EH"`0 =R 5Y bK!& ёHE)H':=@"$`"H0Q&r!q+ [bXEٻ vH M*VY |&MT4pWt2RR=cӏX:iu[6@0iR9Nʮ%wD#;`᚜Ô H*a ]#Q/$qlR<(kflv<>WVǜl Ѩ@`mmm%#nDAN։ qX-Bnf`NmF&k`6Jvl ^nrGnnnmv٧jmBamZѾaveSo =x<; 2pZv.%p.>n肄 Xx&Y*90 4"L>l7R8p6N%Дs7P̣.#T&!3.3 2o:$zZ*m$np)UH($x''`+H*nRp6_LOMqK r,>er0rG.%q'sֆlgzL D"Yrː78 5gU583o0\9C#t'UT6nf~.r'w,S%tэ̡ٛAOtט ?:7 Oڏ9!kl<%H2iN"X$9VSz! X3(-⍞kCYMʰ@e$"0lFɸI}ۙ)Jn_4PT vCC1.C [04/07/91]% ABTT*ͦaZCӁe9 ѣn D h:#@JAd$q@ra$Fi7͇S!@"9 qEPU*Ձ. $m4fXye7Nb ټa3iCOTLֱl/@é6Whe^0gZ)© "{)476S|C?9Nq%vR). iRIӾ H#᜼IFN%Hhkm$4:H hb)2A!Ȇ %2dh8u+Hs)\a;Iw7]#4+t@:Ms^nOhΣBHzE )eY;0VeVżhA\l-p*g}.4r$I 9_u@}φ`A A)tl_k c /@@ 0 'RS4n7AQuŻ6] \jv=uxZ‚S abu])ԔjZ),iL)1e䄣j ȳk(,=:KaI. `d15Ś] ijg.!IW ܫm.pnT v 5!ؼZ A#((‹ "\$j{>J 7#=m`\pyĥXm1}[~76ðor|*/Lk=HaD#R`TrO%2R=7"Z O~->u!HxRR6+mܵ>rT@<ٙ! ̮ Ad5( τ# nކeFB$mUh&ۗz ٝ=$HHt[*TTM7&cgre󭮓K+_^\U*b_N fy1of,i}^~o5L`ƋۄUtǸjx ;iՍ.aHcJ]kZ'1n> LKE0Zr.~)85#bլ90sHIY!W˫ =8Mt4Pj䃚r&CċFivf2 PÖsllgkay(!.#vCj=9yw2A*auKk}㺛b-Jɓ'Ug ߕ LΡ:2pC./!$ƓIW Io=Dd<j>!AoƳ?U3Hynfewg?joo=V /:#I4wRX< (8:8&09;< #P*' 8ø9X B>@[+<;N>@4=|(<>> > "R %B91@;cJDçFdSE'&3^cҍ"aa+E9 s-хbx@*mg5k2/&o8Z|lU"ev 0%61Z9/kژ" "p&";`c 7a@+)A`bC W VC G$AH|E 36œD#"K0ȣc H(W%2h$"D;2<9 ED+c`:LLdK)@T3Aa bC(ct$ 'I c9H3#JӅ -L ("&AUIL0DZU C7.0sHIO9e0 t{Icm#Nmg3?`lΌ)3, ta ˑ |:J2,&ĿuqAЄ%]). ^#Ȁ7W: cFKWK>H4j7y34ْ A /(p\45dVyh7- Q42ȁ-ӥ!莸 (ٙc[~cXA s/"6pwl[rj226&cӓ֬t: 0˲ҕ38-"zN *KAk('kb̎t.O#1ݢs.xgxP7Cs%兰`8"zߟ3K w':6H.C|#>BxFOH.Muܝy9CbEn 9P_ U|diI0b(0r2LD+C"}K| F@PeA)reP<Z T&˜* ad`X !4#I$$S m-­urBpQ&ddL#oI_ PuӇ w%;F>UBݬ)2V\հ \l-s+dR. &SQ`W+z{(a\(`bHrNcE? 2/=M (5s~MfNyp@蘐ld7y9D9t#))\}?A 0D{혅18ve> ,-uSӇ*z:h Ŗd*D&?ZlKamh\zB 5m-ZDaj8JN1` %eRFpFŲ[ b#3z (iMt[X` Y($я$.Gq3HrW#,Cb)+yp0 -ͻV40Epj N lHa.AKQ ] x) ):Jd@%җVrS|w u5g6ۆ..fLuAbA-d6Y@˅.-uam QȢpɀ@ LbJ5_~|+P32FRJZ!ro 7sJۣrew[(N\I[)N5h] y(sCt$)&ThA6V՚^L"T![u (De Yx 9 X+ͷ+Tk-|.pa6c@"S˹{E*3Kpx' Ccvb7n \RZ֊!2&Wl3y!pBRҸg9bjTA+d@zn;frrZt{K p[6q h4ݏ3D 4 Lqit4Ҫ^Rz^VޤzQe+? (5|<`S67#_M1}m&L]D)e:^H֧fI&Ք.5`p&E&0ZhY^ Mg%R"a1C/h% fu%y ̥cK%~ Lu9O ԃoLu?Ŝa H6ЉԢa#/@/?)jj;"uS@ύH0b فkr@*&sg .`њ h7 .Yx-. lۻl AL&iP l p 490A7A ! IP ;Cl= "/Dk!8E@BGHLJLE?@ HPD'DS/MTYEk@ hC|E"4{E@n+w#f\_ø!CB:/pB%-™S »12;hh. -#h*>:>FHȀm B:9!ʛ'D;&ƣ\9C p{! &!01҂\0`plt.(ЦFl_ Ɉ7I?|?(FƐFJ4IJteJH'\.-K @ `6H=u=ȅ=tٗR*!7>;҃r!*Ǎd,| u 1zw@ A 2.jt c4:-#4G90٤JJH`BaNk^KŒ8ČXƷ+s@`:9rRڽIN0dܐ>?KO i((2#= d֌Ux= $2H8P@qP`8 e 锁 &Q=, QH9>U Q3H8ѵ QbUљ `{{3sҭ(P)$R"S ѝ3?m +37U.u6`S+RS:3ӸR&RuCP}9R9=$=DPmIF6R mRmJF 2TxIQOѕ:M@ UmЈ6RIR]m_љYm+VEiџ|vCC12.C [04/07/91]% ABTT*Sp4fé 3MX@d7s(R rłQa6f#[Kh&tQR4  :Q27UjJDR-9 ^7b]PCAm0mљe󳹠rM9J$$F=+47!TH3 "g @!4YMH1'*ȠE[`Xj9U o;B`fk% H31B UZf"q@ :NF~G1"&WGXĄO3@ 07@ ":ެ(6)ھ#++p0cX:l@ZڷCDP8zՄNwy"6@5a'4(ஃHxsd rTq|K4HR A#NRI(5s ŏ 4 ކ&A 1t,, sk̯ O*JVKOE@RCU#-\9:ă8A<+#HΉ7@p4ىKJӇ7XNhS ¨&Ln lVֈңjۄHb (،ِL#lXK攩)9͊Uk'Z^%DLWSggP!b@)&=s/S؇8"Y4S:kaHR>i "Bpt`&6l' v{nhAU?Lj>fY#@hcL;&#Hv1zg^;Z i:< PӰ$X]v E9ApAUƕ*-P`BOs@)&]rdV;u)Bl !!멂 =80T(ih$j'"flР9lZ`” a!IpQM(#P I 9y4"" o hVs.c !fj~HQ/ "` r a7NJAj-xyt9"gM^;DP{! rd4 U; b dəS.1. "XЀm'k<"wڥ Tz.5ǹ&Aecf$HN3}ZԚba%0~cK=rjp ad(ikℰMeAz6d[TUĦsR0|(BJej K#'$1 FxtOpJJJYWԈaJe 8VD ~, K0#M0xT JeSFUsU~AAfVjɫT7R [רmx* 誾C]vt㇯>6n=`Pq6јI 5 @ЮtmeDX*'5dq@A;d%c`=A@+۸kcDjOZ6X_#@Y,-iP۝045x/ **Jdp-^ ufPT +`gl^NGO/jm3”aЧxBmx@ 2mngJ^C!5ʊk@M1|!ÃZE3 HOYof;"<ցǏ$e|Xb R y d !YY?Hg @`sZچBl %AO-"u ѡMAHˈRu`94RN^!upkFn qDn/Pm*w5jg{uĕrlBDA_8O69ю?J[d.L q۟ࣧ}ˠJ.X(m,uq+a ~f@eAN]w8wpn>Z9BD#74I 3x&[>*ۃ2cS9[ (8   XAڈXȘ$3(p&&+ " %$jL> @H+(,HЎ" PՄȇ + Ȫ&,,>pH@<.,ɟR+,7,0Кq:C^$>,?<58Y釵#?E@͏1Ÿ cىS|Z-ER`*`':#W@i`͊ȔHȻ@:·!*(ǡb5Z T0A H * Hc8#숛.kZ=3| ;PE@ٞ#HSyk52"k 9 *ރcl*H-H")΂1:wp 5[ p#".1HF",4 &!S GS>X#JlʌKi!` )ʌf3' ɢ2C$LvpDzŠ$#:%NjڃssgÔx14fgF쉈3(+u9B!&8@kd#;G=Jfߞl I87 8ed`G{" ̣!"LX60:ʼn惢̲.0OͲ^P<[7L{NK)сRcXꦸ͈7LM s@7KBg(8Šj!ysl6Mz+ Ӹ2k17b(0<(XH@xܤ@l8PLDy0PPRȐ Ɍ9qB"씠Q9M D3AؑNi1)qюuJMD/1a G9 MJQ K=;s@ؙxP?҃3:9?@+ )Jx*7MYkEH9NJLG:E#KF Įx:GM3;)qp܃(;ȱȘ$8A$ks?UDч |Y4l#UH͊`Bt()D+B-BTڋIN* (hǸ6( C8D6Lx4_}=-y:קʭoj۱ܠꀢ9M7u->I1""/2,<ں3L:EЊ9II۔RE4pZj3d1ȪU:Fџ M[.A#BAB:DZFI J\ bčx7 @"0IhA {R @0@PF;@P$Y@097ǡ[;X {B@F0@΃=N1b90.{\46 {h;3r7,0$L6d&#JZô2 RZO @&+*+64 /!#:N#J3?Ԣ}?- |8@4pEH# UM;W+CťZ͒)W PX3@$f9Uch6nR7u/\]We$SSyM`$lĽ"28%r!"=--V:XGeX1R^V*]wmrT7=GF>ΔJ7).R9-hVEf|0 F*`0MW4 m~O<ޱ* ^IDCz0tmA*gğc !l*p7a="#|bp%"z C O=jHJ!% @V R Cb@!ҭIi5 8cTWx$>(4 SY3fv% "ᘪ9˒qa Adj@"_}H7ĸP 1{ 㹦 "4;I8ⳳtKHa3FC mFiP@#D8j %UԋNR^(y2&=l.u dJxR69&qal$@xBT>0 ':uQd7ѵ*"dZ^%^yę 8[ʹfcb|QQ2"% B+*194PTM"amR/!CgDP*TBSPB Ae\ƒz+`4Yb?Z#ҫd8_%A"ࢱBíoҽBIID_C5r*GC(Pʓ%)ET+K&ZxH2qM>;ab#:aZjՏYـ@,CnMO@JV |\7X+-gD5K4%Ѝ[\5@B}p. khۆ.J!N6YdiμwMA1_JYFH\R/r+!VQpaZa{Z'Vj0eV 0H*|7tU5^1.[LD ҳ\ g0HRA6O+yDL%EVMHL'3x0ԙsLN 9+ .Zk|uQHg f. 6Rjq,4 EZP nIMkC9pd 9-]aT5*Ĺ:y$XW۠}~ζ_SGuzioF+T\ܝnr9yeڛN:8 5]>.G:lֶxC'K須s,dc (wz>P?B^qy jY|??`չmuN*ϳڟ{}&@gG 1&.M'D:>:!Fέz=q~okp911{{#>g8b {{&"1{@4m@ɘK*!{'&'+4RS\Vlb  ơt6q0;FB{EDc۷?I,|GL}A<:A4!c2 KG<9A@2 G '05tG6y8֑T[ T5j洃njcH|(<>97Ɉ:FKCCHI Z% l7GP 6x4qKQYfȒHH3H4H*x.Dv\IC0k0y9@!c;J;A  ܨy ;|  5j <i "ô)6p9ψr+uK{!4 15q4$)H{!!A\ރd:(0LM rCP3ʁ84;,4G[[MZNkF0J#M(̚~jˑrT>*"_NNTrR(tILd6Nq&PJ҅.ĸ3SO+`(9X'0#*eQ%,Dc !$@+Ծ54 : NRr^ґ& S\ۃ{D!M猈A9E= 0>0+Ҁ&gBK=ij:8'[~4m?tF~aQ#"%3NS X53=7 ,>M56w@ϟ(нS7<#3EWSR("4M*!>%a@ARB%x=D05bԃ?8ԠTUmT䴪k("HWKmRpT#Udi LBDMAX&E8 j5\rtìHH+LvCC2.C [04/07/91]% ABTT*ͦaZCӁe9 ѣn D h:#@JAd$q@r n1C(Ds:$@Qj#]V3XPH5x:FfP fS 8Rfcls9HfLfqI!t0eAU @H hiݫ+ac$giΜ Vۚn7fÝ_bB(Ae24B)*HR$E5{|6@ۍؚ bsmkx7T@H?Os b`'>=İݨ03 Ӊ r66 C9GTW# Όr\'H}&a#6kq4*%6#T0c*#޹aΫC R6 *ԍ=5.B0p5̛3`SJ2H;&Rخ(oSB h(-)#TU\&S7ңac259C43ʏ2;S/r87[#9c*CC7.SH%b=/Y(s-oJcX *RBޔLJ/ /S( K2RDѕ27!@S-%9\O_?+ 8dبh&1I&DDJ5vCC21.C [04/07/91]% AF(pAfMƒIy:aIh4#AA)8@e6̲ ' Gф. $9{?FS _BK u01"Z SqtC+UE|SQNS@(ZiAt9 CGc+ #6&`e9!@$e3Mb704" Sad2ĎyL,A(0T;XsYIM0" њ.e2kf0Q:vk q\ >#y6N} sH98@s6",6J 2 ; 86 K|2#Ch $& 2h@X b) 8!H& p#!* "J.JF&^F#I rBÈ 4 +ʿE,Ar.,,%Aʻ3JPa<8ړ5 ͋;8NQ.c*P s `1DU8C@ZǃP#;c @33]5V#H9 Y!Ȣ`!J g6A5R3-JM4NSVAK5}QbX5z]W|` 2H8HpH`4N 3VRsfb.:jJg`s4MC6jPa{`V]*($d3Fq13K۟ H5 SJ: *j7a aHؙ:Sn ;v.${%A)JEol_p A|o5Im0ZN=7P!0jGVc48&<οF/&y!\'k ݵ}qC 8p jH)0d LoApT ܘ6PHBC )Ԍpp7ԨO)P"B !j փkQ=g7$Ue,r +QIFQs=h&֛^~`/&(H֑f 4.ZyZ11s;cVy(q8FItnxHh/"#GLj/Y"z%k !l +U i~7Dn 6jer:Y<ǶehMu/~ml\0rLPIf0A䅞<&T!)`Ҁk( J' g 茂39M@2@GS(#$l)85L(q~Tb'L)m)L"UM=C(i" ΛNji 1T$WՌբE~,){6,EdK0D-nܿjU/F7XA>1ѰUj>3r$8'*IUh$r)85J-{{o}XBz3Vp4"~ Sr<5N 1;QM3!@Ru`K`P2 aP (**^ܡW =1=8}` ନAa S-yA,\lLLq/rn4%vCs+*bpƲ2"DNA9 1y rYj0en6G'][(\ (8ك4e )\ˆ7SRf KN #nU:C?잜CoBi8beVP h&pes-:d6X+ZUcY4u4~ f؂ݮԵȹ@M Z(1–7ʟ 8$ZD%:t(s1"oxH0"˓JeoXmZrB訲X(S7I< <X&(%1u*%إ8@@1D5G7\@SZ 񖑻`z$ E0Ţ D×XAx0`D蟹ppR A#*γE0H52ꟐؾDKf`5`rU0'%wK-Tͱ"e ‹'nzc D=Z* [͋0Ƙ3F4P:!7*+>H#\ ¥aX&H''`7=p^2@H0Hr.ܥ"|Cyh#BD6Ĵd !".{rM4 3,ꄃ4(RA ])57<0O L`2`1%52*Rz*'Ybk8b >38B,=9ȄaWʤ889XplolhDPijHvCC22.C [04/07/91]% AF1n2"@ ; &XHL" #aAfC#Lƒic4 B81f c2@0Wɔp &9' ]6c7q"A'j@H cn0afӝ,'6e0Sk,Mf8M"%(e&Hd)8E,R=-H^*P&3BLAAt9lvbnWM$Ts`eSժzF>#Yw=t(4:,ΏIj?br,2е; Rڷk0 l+1LbvB̓( 43TҴH@Ѵk^6cnM9Tk۰; ?o @C${+G CMƬs٬ DMz65M"f=o7 09Pj* 5=q.r3( O)!3(l(Zӕ P0DQPFKXRUD\$c8S;4Cd7i@Pa;%hv 6[bX=G)u<=tX0w PH 21ta6Ã9`4b!#(anPj}CY93,!.=$S"@2nyxX$JV|N#%ra{Z*YM]5WƄO[:,mz3^ΙnWL7`6 B[Sl`r!7E9AoSuI 59hZP:rW`U`n|Q!z| ܆a͕'7-0C͇_AHCLv]_GuKu.8uO0ޱo/7iyiGՀ} Ұ15w$VcMe C(u/7i <1u@;O $n.ݵi ANM8R&%&Ag M,BgAfw '8n$4P'HGQ7:iC'@>h T!P~A S!B#bl2&L0S.fLٝ3\ aOzi iB)J6}(Ì6 Cjp E #QFT 0k3Øc`VfS` K$rf(I@N /0iga˧эHH6_ )z؈Ab`xo p6 }5vDc(,} I aiDHRiI:D0xQa 1ӆ.cI d d6, ck i5ڏ? l'i%3T;'DrPZ-5 l01C_x*'(dȝ>} 6Z0uuVBZ\Fdr_L '֚E(,飩{~zH\) .${NҬGD1N4Y?H`q AiIKC "LS`$E6=NLǶmݵ'm4``n`LW\Q I?{]n/7D|1 +` 6 dtz.2`Sv<'cf\)zf%L P7]jEV9a[oc,=г N)L<:`R no$J j,%$P 2md0Gl0n3 h9 ƦY-,ңm+ |c9DitәPU@[5eUuC A( V*>3 ,~hoYG;&d6QVuwX<裕4r"u)M\k-a넪E~(%| YDu9b夫HtX,"!AfܽIaסŇMaG-İlB*#^cǙnEϹA 9'9˔o&Sz tرt˃.uTnA<(@eA<4bح7]w=7Hs\]n-+crx9]Tq#Y (MHrK-~@ scl10G n_eu.۷=J|po̡t1ܶkx G@EÍa0vؾdӑ\h ddjʿ>;ܼp p> CףP={3>填ҁۄ"pX쩛!!`-1AYt,k]{*!mB\&>>Ì@B`!< A@|1T2#T7K(x&a!Ô:"z07 x3ZKyC&C h:05441C1Zѭ*Ќp9h2"&23? =[kG:;+%1e,/C'2D2*Ip r+`:,6Ι: kn H0ʧ vٯh2:ᙘ:\G7Ai0 p('0q#$G59/DhF,-Ȱ3ąHdHqpI<2IȢ\Ʉ} |.qmԖ$+ x0K@Bܡt\\BB drLC-+B`@lBÜ03LL7܀,t1ZT1y#, *4ʣtAukLM43,TlaZp˪j2i7M)Z*816Ex24@p%Q3J F1*:04iUN@H{u6=_12?Zc5ڣ14 tzZaփOթx4Є ڭZZK fF3ղA:#]7kcà9H=X"Ǘ0E82;d0]$ɞէ2 dqN948]Q99ΝPIX^5ޝ1^Y \is 0 Ä:Y5ܷ61\&7镊2! W9,=ApHPvCC3.C [04/07/91]% ABTT*ͦaZCӁe9 ѣn D h:#@JAd$q@r n1C(Ds:$@Qj#]V3XPH5x:FfP fS 8Rfcls9HfLfqI!фegFI̦Ý^ f3Yp(@ Ke2E)KDRsɄZ0cbBl1!ftnNg;[o8u7c.;:ݨ Hv-S0p k1c  4S X-!%C(C躂22ޔPC/ /S$j,sJ#2c/ X*-.*ʤ3@R4C9L22<#: x3l2rl1+5Ά܍(2 37j Se;/CLJDDuYՃUR8#ޭPt-v5WaVr]H7T X(3Ck2ʱ#RLzr jP@\!TI)-8z_*2 +=AAP8hp^Pl46 ,9 73ͳz66c:; 4 7B122]'>c1f>`v1ihLH]hW3ּkA4X4@X#:m4Xe3\*4Xѳ6a(ΌNM-3Ԟ0Bτ҈V=0n:5-Nhӄa9lgB!Wcj~o!Cj>XA?7m %ʁR*Xpf Apc-"$H-hHvCC31.C [04/07/91]% ABTT*c11!a6@sr2) $=(0*+&ɋܻ-*zl J(#CQ2T%  q#Q 2r. bvr i:&v8<;J24!a=I#S453!DLS@lP74oSDMR  CPFCH2P M{?ԴP[2NzpVU8>s:D+F9˓U".PATY889U8 g6k+2;[23(P2f5Uu2Xv-6Y6P(@Qa%X]ZS|a2Ud`'"{$[? :Cr|\WŹ .ct 6&(ݺD *&rňi~y6c{HʴxZ:l73 T ֝95(Q"sM,}ZY Yenk߃L0AՏ↞KXUn TxIr.7jY hѾ f=ʠ7T,dQJ^ή7q ySn"Bq3ocIR.Mӣ?ٳ!Mpodgv5J[4д>U#U V;5^W*<V +x [(.Pɣo%ݤٲ\>JH8{%: &A0"{ #z8w<D!KBX3 Q?\4^Bh8'BXs{ M=*fM5= e-& u}I'R4$H@SڍO4Y@]p0H$ |ɆK &K/gCdяTB8 :HrXd<",RaDbO1"hYX j.ؽ# 3F\M,l0QGcܼH]G8`vm陲'Mț)!Yor>@Jy%%!74 @OO28E Lru'Q7FBड@G@G !Z4Fi\ɸYbY, t Z{Oeug5Ʀm7Sg?,>EMY{8X,<\/Op=nP9VM\8Sвkvδ[%-yeĶU6=*hK,MupTH96բD>À=%r)R5ShZ`U؍JJ6"Af+;{T}܍!RWT%-w2B@IXBvpZh ٙ%2D˓;68XRBJd+Sj\[LH|A"0\!M; a* @ x-}s ܵr_T*TFh 9LO^$h9fe4ݜ#ڹA5~h1жk(,##VP/eavWJ#`UאY+#W 2er 퐝@{v)rx̣ӏt.*_jn{ഖ:݋ȸ/ E3lS'ώWxh,n6L;W&]hHN Yhۻ8e Xǜ9YAQYǤ$s6m$\.&ȡ0sﵣgφ=$$t+l)9G$> $b~[3e$.cm[){ A+/K~e%d?HnߜV9O%^YY=oGPI> y.;fxI?s/ t>-:Eu=_|vO{#u_~4 k䙢$э((:ThA9q2C2A 42O @yPP՞q (l!J@q4Y92ϛ$! 릉@b 2΁DKpj(25N4k~ ) 8>+J<8Mt*9>D4K3E)À{!86$Y;DSAEX=6E*DCTqD+!N)"Eh[@8l#B2̓ΘҠӟUzKAԧD1yBLtGrYǢ{Ǵ GÐ5c@ȭAL$'*XޙjČQÄ+2|,B/C 1pʄiL!5"ɴ$n)lɁ_TI7BAS)*SiF]\,,)\/r[# QK 1(<@8 yȜb 91 h1 8C0?LT@Ɗ̍xѓYʕ.pD ܉GL9̙̍8@@XpIpLK: L|%PKɜ̎8! a 8 V("**M7M\xHMKۿN$M;MLyNJJi=l8 8uB|QJAɸ99T85 Pй= [ aÍPJMQY-ѳbC/PuJ"@!PrR!R@(?E%9Pt'!*=-RPu:T1H=SHP<M5TĘ}(H 9mP}>TS-'ӔSUҠҒFvCC32.C [04/07/91]% AF)1 c R MA6[.G$J)5r C 3 P"B@ B `+CL C!a?S)(( cu9 "@ }gC)Q1"[imK@e6̱9nhEDe)0Sˉ ̋':(7%#7)#/BFʪl}M®[AU({5*J\42I/ /+@A K-Ƞ"k *bH*E@eK-ȓ43  #@7 7#*T7IH0R3!ZeZVt r03P4O3ܧ*RM@Kjc_V r4`32,枭6-›FE#U#5e.S4;Et%CBz `1_er7@ 89lcxSa-̗ 5MġŌ΂w<,Ґ 3A+53k|HX jz1Xǃ˅ 'Li)jRk*;7د[vn F㤬: LI)愉CZZd-$)]Ci`-9 AҚZBK@1VCpטLpP$N-H8Qjkr1?,8il;u1@pоO 1~MM@ a: ޙ-?Ĩ\K{ ƶA9PrZJ` IP5փo hljS,7dBHDKР8THpؘ\Xb'A=!H)Hr^Ȝ 1|:DR#Q(E &xLc!,[@p3 P e(cs# Rz˒YqE~a4H-)DȲژTwiH:*Tj]d?cH &?=\p arĪO1ɚvhr"|_oN"SaIf8m>l-o89'$ ck\$FL Wf􆑕-btPQ#P I :7Eȼ. S)kM"LI"R E-Yh IG"؊ۢg:SKaDqWt'k0$!2J{OI%gTH*TK s$/BA4FLhP+d46ه!n+d"A:+'e1|jnMƳ, βhs!*[d":5 Ps ̺|S '@Vh[є(L~Q.ίW+X0z/UHŖCFFj[ 5P+>hœ_(DY,i*ԵgRYLk"'ÉJƿD٥e .7{xqc&l~%#*7|ls&xm >*chT5Lَ]o,6v܃ՑPa8b9?#2#*(V t\WѠh\_/@A Rsy-0"a)d:&'g|WX 2P30ji:k,JLjyx#nHb $:cP1.J+ HgnkWpCzTղYA\6v\Øa7r Jߕ[ dp3U +@7 PC%4՞]K \Rݯ78&2d 8s8XwoLT$q=Cg1Z4ɿØ=Я؀7)kOJN~pz1ZQh g4B)|A !Ɛgdlm߲{V'B+T#nÀ= 2{?j_q/JW" 5hvCC33.C [04/07/91]% ABTT*GS(f&Z>2$:a9'dFBq:pIda/ FátE"`S%flUbA3RQtB=!IJt:bVv{}un+cxXOH$ 2\df (ASaS0.|eWc?+c)#(4ixJA к. N k < 8/ 9)s6D?Qcʃ D K)0EΔP.;Á#E(VKco Mr°!/PH62RH2 8R0)R;;0@:Soz*θT7Pn2J1UBFK`0N8%C(9*q\h}`+1 P@WC4~JJT:M zX 2 7uP]@;H 0OàR5l592-^+|U9O6#vD wUm߸`3U K5QpW mrM׍v(pQmc(85NJϏ  H`$4 P6e Ky{ 2iI*$F+Ev쀑І0@3uc%CK= R>Cg: pˎt#߱GD6{DU\'IuT3ʏ]l%ؕe‰x\xn;ouIu R{q|~Lwа:;,9I%z(ϥ6` A0 @WRMs,/!/2< <8 T^yAX*:B֒⪆P(da hch#%$QLRpąV$U0"_0Ŷh$4PI+CJni1U"43oVI`mDDu]48LiiM1D]dBn$2SmQ&0 ci7VRa*4]Vb^e?(H,S Rܸ* nSLĝЃs5 ` aJ4R;!S ͑]# V Ҫ4?8 J2B|̃?q9&@Tj:s6VHt̗HC;o1@I% .\3 L#5NF3,&ӡş2W!tˋbx# b+=SI D5 F2p3ci Ck27HK3҄*=σ幾?;qkTхV0HBPa.8[6مa[S\5N$U .q sL\qiL4w4sl#KRT'2K@L} HSz9or[DOA3+m<QԀIB.7S44 !KLr%JZՈ=Vj[t~9b5TRY pƵ^h (0(uQX"]w[o.+eyB LI%$O0Y+"A! b$Q\ ^A 苚CDpOX�D a a;9BE`;" l2!( I"/5+˜Hy2o!J9y u!*KI>wc*!]0k !ЬAA tZ~[ } YW>/ H pmpо 81.Jo/QLN9t0e33Zeڣ"K *Qd͙@fy&Eԭ4N@ZhPsCi :rI]B8M2FR>­?(q41A&L$]) t Q5Dg$֞:|zU CT>Th^*]MurʐAF G]$@(t4S\1$)Xg&.)`elFi;@b~ g T:(%#sA V"KQj_uһWDX;(P; Kȝ$6Mb eJႋ4V˚p(mc۲ ,ѻBBOh`QzBYFx!@" m֊TnBuQUkȝaM\UY0%[L9UU]T̅[P! ƒp+i &*%rY 02LH!Rj3Di.&s70PTOu)g- xBS ڑC=ʰ6İbHL7gĭ0,źwVe!y,({o}7_~E;p&/`Lh`<*Vfv`Zԉb1fnaє7cyW˰9E|:!_;+6=Sw=qs=t-s=h#cӳ쁌l9F 8tX9|> ⼳`;ǫz)$qz;1:p) 9@D*2 `&01ʸ?3H6\N+;M|69OOͶ؈C.F xP rLM 5ɺߟ0В< `9(p9Lh j~ѫĵ02rC  +K'y7z]Ǜ+y!R8KK^T&yKp:M 8X˰0S<==J55>01H-CGJ`TEF@5G4JԨsEUF5@an!y"O+\4&PFXD[s!|!*mUUln}H2Ӹ8ELp' X$ V@mNOԭPգ2SuV\/!WōYZrLUT5m }`TW25THﲓ*UlFUE|4HD%x vVEtګ2&!#жhz$N=IH bIvCC42.C [04/07/91]% ABTT*NFe:Lb7Nbf0̦AhGo̦S8B!Fm1 !.m̱4gQbci;)A;`Ӂd H4dG&anP,Xg(Du6tzv9E6$r DyP""H R;>`pT$A1)@ =CN$ЋS «A/J(@7@< o)riţL^)x6c8NkZ1:p: _-+}Dϸ9ˮC1FScˏT4H)Io$)>GxA ,nkO '6db%؟8dҘ@V)H"T '"DTNU;1z >;8F^|Ih(z 6Ѓ}ueʎ]9F>iQtThhFma7W`gT\ UΜO(>ڇ*F~Q9Rle2>UC]X{ d T("H#JegNΏDZ@1SY`;!2bB` ϙsi@u #f8CA] Z&uJd\ f$iɶb[ZiՆ4׸)_e}Y֎DL> u(;+YrfU)u!)Ɂ.7ZcZC*5&KWx!U;0c8TĬ€T !4$A5Ͽm cdPZ/#?d !<@#1 `X / )4L(fʸ`LuݠSAtIX3Y28;fa LG4@( ( t&C-;wAe m4Vfg@rי5{Sk;wvfۚk~E.2}`D7MptY!|8#> g'Dۛdm ~6/_= D'8{kMp=Y҈ $nY' |;s@d 8xwPkϸ= ދ)h/aySu~qD2q㿳,4?^x g"NJGC~HCxcg!uP6߬9z}0C=x 7^_r)<-v9=t|vG|߾&zq疄~x|cyJ}4n_o:|߃>>; $:37"+KB`lT'ˆ,  (1P"@KAKc?[BB$ T94)l7Ì94 w6 u`x 0`BcA,W KC;4C5h7㠳˵4 zûC6{G4K624VQ5 854jLel7T\]{,@:\Gf{hƐ86iE\kmnGpG P77y8`s@8d,;U;r9|ȄȔbHAAH~Dc HsI+I;˾;3D:T\rһ a@H[t:Ħ;I|=p>ǼklBILIc̗̘3@I̩KsEKKH)˻>:JJTHü M$˜83@l_ ITJ pJ$<JIL,aKD\tL{Kc_8LAL MԮC$ɤN d|ʌ=AL\s+A'\IlC/A7A: $#d$%l/[LBBX i 'P)J+C4JsEJL\Τڲ+dN AtB4+$OOŋPt(PBPT.PmQ1PfLJhvJDݺFJ\ ':͈˵D%Ҵ2:3M  #ąE=E"[Y$1.mac m80 $1=$1 l80 $1,clib/s,$1/n/e CC -M -A -P -O -I CC1.C >CC1.MAC CC -M -A -P -O -I CC2.C >CC2.MAC CC -M -A -P -O -I CC3.C >CC3.MAC CC -M -A -P -O -I CC4.C >CC4.MAC M80 CC1=CC1 M80 CC2=CC2 M80 CC3=CC3 M80 CC4=CC4 L80 CCRTL,CC1,CC2,CC3,CC4,CLIB/S,CCNEW/N/E M80 CC1=CC1 M80 CC2=CC2 M80 CC3=CC3 M80 CC4=CC4 L80 CCRTL,CC1,CC2,CC3,CC4,CLIB/S,CCNEW/N/E L80 CCRTL,CC1,CC2,CC3,CC4,CLIB/S,CCNEW/N/E CC -a -p -l2 $2 $3 $4 $1.c >$1.mac vCCRTL.MAC[04/07/91]%  R* @ !ͧIr㡤e &#yZ y<@b:ѓ f#  4c0fI?I<`v4N3 Z)S2,"l0(@b0+AETAE, DL8NB29'6C)EFб#P: P)(&VB,*!q }ѵd170Č8#(I3깏L*n  ~1 `@([ոgWk㒯|TZ-Rhz6PC> TQ 4'#d27n98$ɜ v,7 ~428l<(*Cc1r !|%9f7͎ )Xs 8@ Q>gAm47 Sv6(Nydu 2 # c"`n w#(0#0mI<Ҍ#)P|抜 -[w34N{{Fybg'9!~J8Xl @"g _; y!:AByaJ<*BsIfԓ;w; +NO>wٱ ߄7T; A%æ3y09qŠ0l Zla$Py.!PJrdk 5ZD A1æY#stȚ2@k'(*)(A0z;o! :ŚmCw2EFE#Ĥ%@I8!JO DA1F % &д2ᱶCq3H3ta40@БBh J;C D3)-@(eT%cz ~OH7lJ{Pe*㣡rFb0$.h0$PB"ؠL%b0`  $I eMH:VdUj=)Q'i\YRkLP^}]Uk+} T+z .VlQFM4'St?z eZAiZA AR! F lXi\T8\@9xRJ)P@.5sm8; m ?P炑| aZ*õn1auRC|)Os3hrHtőҮ0 @g(7S[ {聼aopLB(MU.bBy%L4f[Yl ge xFŽ)f\5m&s~[ʙ4|6:&!|TNC@_Dp@I{a3iDhush1*ɨ Yn" xg$zI5jQv2;L)fTL6 & gz!"- ]! ϣb(1̃5} NZq4>*]7`3%$wȖ Sb:AFZDZB`X $$W:NJ3tUL)) rAS6oWv<Y [l X9gme$ ±bTpEw )qR8!-Ub ʥ e`A(` S5*R۲ps!~j~J ̥8MifMq !|;&o9d!J;NS?srAa Kyw+Zp(aY ZR:P kLIH;VvHf[yT`gB_`|U0V L,0N/|קs b ftisv 4RvU1 =[nۻMoCGcr`=n6}t_wuq>5:Y#G5H75*(`<(b q*FZ ;2<3 zjD,*(Y8 1ԝ3%@<90bX1H4<2Z%"`(8&+t(,şYý)PkdBx5 *FAAp0+oYer` KC'D2{2(AL85;L7;eh?)E'dFC:,:`75Y16 'k5")!HDzfJ<GO4 2+3RZdLlLADL<[x S6#$ lI#Q Ɋf\[9q>;*I)$2쬂CQ&`" !RH'!K1Cs*+,*m BگF&p  [ނ&p%|LЌB(KJj2L6328 QBdS75 Th$]H% EEG z: ?HP%2՛DTU M &ucF# J's%REo L;۹dJ߹ ԐZKU>T).⾳I 6 (kxmDhȨ=Z/pQ%WC ntNQ%Xdq&F#׸LpQTHT7%Ղ-8Ӝau;'Ig\.T#DT0C͌LL|GY9<*9uH*\N6^ M_TV,LӤ֔QX>'rjs[H 3,m# %ڜYtZ3]%HK&ڽ@WԿ\\T&{ǭNE49pXR#]v݇!*Ý,T=_*< =[֣%12BP߳A2*(=x- )]VЪe04]@Ve53恵5_xƠ:bYw*I9DbG M[2! ;(h¨շͱ8- K8 Pp&+=fQ\UE-9Hn(D{t)I^a;W @9 @YX1(7#X >=/Quy-p7rt ףV9`+((ظH"|;p9( Te1H &mLgi dEq̣zԢe0U!vVDfzfᶎDj}V[׋}ط}TV?k֛!E^bվ \3JGJs>.B:R@ݤhNkm{ I+ gxł+2hC?4h͇۹!i;Ԍ[!ji հksu9 D )RIaMZcƱEQ aVEV[ &):#81iX48c!"}ʌeh;2a7["!5?B%vOѩk=gqc7yͱ1"ޒag ImdI>@jWFlRX&cΪ-+$]l@q(H"ܗkz^_C,]"6&V@(s`6e881-vqx73AR֏ȗVI(z:9pдMx e0:~XH8q RK5aC=e=Æ K#»Y8Í8#8r9/_gT9R[t.i_ i3A>@7ɰ.чtaS*G}7=ȀOo9Kbˮ\[ӐN] Y}R1 jDwNByYkEߏQv9xiMYYP5)P7El7u)'U hHXYZo4hnr#:j)r;F?:'EG(fu'C^_aţR7ez/pIc8/:'tݷ?ND(b}k RЁ֤zbcRSD֍~?BX,f; 2VW&~魁4@{$Zmsz &x;W>G5ڂ׹ B48w{D7dM~x8#(N2ۍ 8ט}Gq *8'OdWQ*#XGi芸Btq }.WG8CSJٲ@W>{ۂf,>=ۧ2p '™r>~,O=>)08)8ٕ6ӹ&HPzִͫ{5_hڔOz]H#nO1'CVjw6V+z Eu7?$< `뾝6"TrKkJ): |?`:5W} _y|Wח5XJS%owu[>amy$@-#}EV+\=#TX>T AiJ~Tp2,= dۄ(N=ivXl$!:o Pm2 ؂ DPZ[9f 1ޝ|+߯_$ok <ウ;X)Ӄ6V3K? M7}o]'/V:zJJ)]tƞۥk7>]f~9~P>2449%-8#v1>7}ߒpkrie'RW%NJ(uߓ1""l>8^ӑ*,b#>02(t&<~צ?ǂq&TX>2( QKoB(p`:|ٸ"_R1=P) `:~ViQ!e)Q(1h{R !~y >|Nmqf?~_7-8.HB/ǔӉ?}sz H4&XL/@$޳@1B@`/֥d8D:q *l]db Ǩ?;Y"8RwطkNH.8)$ty,,b};NabC&J.E'+DA(ŀLV+>Dseص%>$qϬ%9'h&\nrI/USRX[ +?v@ sW>/ $f:BG,he_AkD:zk~wnrFڇ(BpuBn T\:2>TX>儴uvM/FnDP$o]ê#xS$>,));' I"ё8G]W#&X:_WQJcv8J}3}3-&!zߺ}ֶk%tJw۸3|}ڮCM:lT(8*$ņ(%羨CtYXXb@ h L;Щz:yZKeIɽ޹vϽ 4]fHAWT7~ X>T::{$; "% /2 #JN7|H08XOl\=BnNQI[b\gG( rf2pKHdr&`߭7V&g=aX2@H`{{R#{t|Ye9#_^ya24p Md:gheХ5^@&e;&.+?0@&3@ `"H?)" w98=+ng$uX>"ھrKx$}?>@))=-w @ā>wSv,?ӐفljhL,CyEWЌX[N*V͕"Xcx?`k5w>Ё ct {%*Ȃ'3|m?:Mjr7 ھ X"^WwN8.b)Ƨ":3Y]+ D ZP0|t)k@ga+&e<)7Jfc-Mt唚`"rLvn[NG1J\dR 7No7wx!V  $FlϭYw?p`:_va4oUkmރ޿:,; #-pl 쿌a4y(`:gx! JdNj鶞g!7h&H=BԞX9̛' `Bf]镞>~D,S^ &E)* 3<+ y7_X>~O"tp`:ߓ3#lطe 8qNNr?Owve,wGؿ99+;1cO? ط+5n6,#~zq$P؈70TK$Iv(Ae'B[2p` -  )xgI+|N#a>8, }ߒ^cH:h'c 1+'SDߘ}:e9E.-Akd=g:yі>Q%]+8rgM<#D .[-$*B$$/ھ*p: #C-'x"J(b^JT" lCBn~9o#46z]=yչ81s!}ߒo&.%R6e;_oo!On?H$sT\)8#~z-"_C%o,S,}Œw!Wok?HfNN{ieH8DaVo>Rȭ/ה7l#}?҃ @tˢ m#]=g=>v ^^,lo<&TX>(#*Ǯ(9]3H7 4:8lHЉGBe>|ܶ}'ɰ~9#'Ҋxap.ȽLn+YN@)d.0ZC#~hAH>IHFa˜EWM2eXoW=M}7pَQ1 S+6G}:VnAL#F\@:~|@٥2~h@#>>H 8.r"Ӑ;Z Ռ"oK _=<'f}{3H7Ү젊JeSgyu 1x}\AKn h@2Kҁa"d>)/$pkYXgF3H7&5MAK'<3 oBdnFid4gޚNH-k*NIk,vĚITNH@O0ZʗKz#eHx0.C7?ye_@ah{zہft oK _B$cH-ITHAbW-˽b5X,xN3u6ǯRaSV3Nz>ej lXU~BF 2e;J5&Cxe|LMWBVp9w@rJu_+#.Wu}q 3 .C}EukeƉ~qހ=- X9̛'EFBo@V^3IDlw0rNtaʳOOl-qLq81#gGgHa9 (x&H=^s5'nt"?:̤Y M$PH 1Q`:+ՅQ>v^od1̔n+nt,Gz.ʳH h8iӿ Ix1HX|6t 3)5M-{cqtv6tQ(,ť?k@xFpƴFt?cU6txweØ P1~ ceMLIҠ[.D#F"  F$6t)u -`i Jq:.ʳ~FMQe.vV6S4 7T $ޢfӥdLcM1sebr'7na"d4@+LX9 S<CbL`F?UOXp'Bmejjh> SlħLP3pgPvŽF@$| xU,p~y9ߺOg{LZpH߯e `x*aoU2:Z+ j4vKT xqp(OJNh?x9p>Ü :=6VB~}R?x: :<>}7H}v6znk!6Vр._IFij. w4^:ꞲX7QK v6zn{:KCV$~ (U94yo9o{O3E'(~ Do2 H-}*0eXB $I pJ5!tX6VrBB"XB .}W ;#;J5J (LH x>lo,W rr[nns7?Wq OnR-Mu,>TMf4pXKg_9FE}ٶMf,bg]l;vRwk3bD})!\>5itA鬸 3hbdh߯Biz t}xAQe.qgS]WI.:ζAI2C m(|'1QPMOfp.4n+J hBm /LJ& +%Lhf_IئY( OrxIDD}7vUD 6M@ ;#;_,J}=6V78N{$ @jB<`yE"X@m"%,voK _=KgLH+3}ڗ@~u%} SmwskWE022m(%l+JqZN3Ld?v<3bTɗ5m|ƚOFνf,r0: ߬5km ;#;gu65*[a24w~ t-o3nS%%LpT8.s_qe9VŁdV*+nsV_:[{8'Q~BG0l1؃دng^JT _ WNgysOߑJy74r?cU U07I6S'1dNWGD}KcZ\|NUB޼҆,ҳs 8|) hC^#^eXc IJPn].y3J>2+$,*5X") #'JDG9l7pgs>i3Ĺkf{9p`X+t~y`(-؜'*"-)P)B2} NDg58+'q"!0@'fs%:VP)V)p':w>|%`'8*ӎX)`_p'knTo~YA 'zė5!ƒ! r*"-)o)KJE㳙wg  ||7sR BP$d4j`,.]ʹ5zƺJߥV=j+yZT)a9sIRI8Ч ")_험W;$-.g)dݫȹG}9Hsfy?bK(+$jt x~5"ՖsDꅌy9e_p$E݁coK _IQݸGy0kd~+?i˃~rdm/z~턌n> U6fL '™3j4m1f[&ㅨJ&]GxX"a>a!?&oK _/i"dբ o|S(  @FvCCRTL.REL[04/07/91]% J T& *TB`2i4J QpL$hX$U P!QGD'`d1BDU(b9C4JU" t*Q'QhB \XNezb*L<E0ZEpY%U $xM3*,&i!.B )  @V @e@1Qvt4Z]CEЀXjo@Sb@*@l0 0`4Fpa0c&L FC)x rLHaGӢ hH q` 4MG(i1"** h.g9p  O@0 #!5X(b  1dU=#I "@ & |$fD0;!mVp"hJ0'NAt 1@@q&3Q\`@FDy9Fr6\eY* IF0\ `)jEPc: !T 7E$0Έ>@p^d.2]9J` PJM`v@hA A8G˜A~@ @BSE@$ a ͸%o0Y*E-X L:@JF(o8hdU0aqb*kpq(H 6B]p fp"*`~aTwR [ ["4!.8 !s@ #C 8|SðUǤ ŀ `=p B1Z@-\ o@]I`H.@*C@ !@D p;`dP0K λ0 X.s`"8'l">'T@0 !|7V]snuϺ]% d,g:( 7 uΠ^¨t-ư &,@F0 #h0N-B`9"UBt6EPCtrP1] "Ldh`VbP/8LaaZ6 `L\n`\anb  D  ` q.P">A BvP=  (P8*(lzR?pa &LV2)- 8#2C _@ Bα7z2C@ )!!BA"QD4TFa Z@_$_1'HWT "HxX:PΡ&<hlBP)b/}>p` ParE.u*+V"!l/!Q(h T{t` @ ` ,B  B}h0N!N9ŀ? xN,( \  , LȏiV @_xQ h@<ERe^91CPX+[Řk,d./k ZP8E=CT:11h9Fh3 {G03D- 6`, B,PXhhSQ6 !c,6B)@Q , V-`=Fw"H8.*8#~ÄA H  9 f G !|8ohW[:@32 D`1>aa I0[n0X%X e 4>I<@+RElt10+@H)($4|.Pqȅ BĤ|m4C@°Uב99 bk"Ȕ0V3Ѐ`3c7APFLY \|Z:: ɛ4#XR~ 5<QdA,REa-!Pؕa@d (kW` m" t@u@0 `  d X@l.daMXbo|:wdd.Lv`2A&!*m( g!< Aar)\ ,>)x atF@ &> 2!ϏVҠvD0Lpnra Jl `JV`A`:_P@!`0N  !2 ` :  !b\Uan!`A"`0L`: !bNDAP!R!P:AT@@ !:  % 42!P S !%$D}!TsQ R VAhA8V `R#NPA.'45qt$ )1G4q;QIQQYWqksq{qqq vDELBR.COM[04/07/91]% ΁fk}^A˔#3n Fr -^H#ţ'YxFVltS I! +GDbre+f.ݔ'G[ S[ Fr^ ƋF6u(4#` H9Hr7ݨB[-pm K&ֻ \ X0&ѹ.#̈́LYCa;ZL8-^`C[KS\/ 8H=b!npL k+9e!6}m H9. 0 뙤 >F%⿍iopҖ)jև)y1(O ds c &)ĪCFG .D<'2s&E 1Ӳ \fpBl+H\aI ?ofM 6(i8\@ffsӄ%MK*8fa *>)mE\P\psyDa5SVpu"_@%9)Υ[y;MځU7$`CB۳q\-B[i]v1j`^L,&$w!GxqًSo_ةd#`2 4pt( 6 C@;_!lC@ C10.a94p6@\&B@0c밌K)8mAd9 nBp; ӜcXm4 #= p:@Ax<& xC(:Cp2pԽv 1d:ep O\1o|cxzc*z }pçgPC9`}F)2")&}Ӊs8$vA A*p* Yf}Q̚ѩ"*4핵f L5KJ9(C)<^]+ ѠF^TXBWeMXG*[HaW*P'Wv2a-<@.6˵x+:gM@YL#vTI[a.+rO/  *$9G.%="Gz0~2abZ|2czŜ<7@RLH|A>0-//@8F)>a&r:4ɘ8GaZ+R9P-a NqLa0@,q>XXc|B*["L> ~b@9Z'&rVܿ' /]1LpP#Yx_c\$\AC4 aH&8@,$t1Bn 1KTo0Pu!㨁:g94Y A,7:0 Oj} w(5348bVG^߁\ عA2J;!|,< ZaÅ|0 E\@ui|) іycm }w U`!W`Lb08 )XQF@1 0 #10sTk" -`0.z Z}[a<,4@aLPVqGiq# yUAJ m!^aX[R"-Pa/K=4B@=R)00'C؀1r;DA~$a;~@ ߧ@.g @ Y ]lS쯩<!u=X}(b>h;Yh0xh&?JX@IMr 8JK? ] =1T ;ˀ e,kHկгr/#;߉'zbl*<$ P<8h@BI AȹЖp^=\ X+C84HfX{\_(hrFdbґ@EF0P%<5 T@V-폐iHP“薆Ld Ms l aD; r?"\ݧ|VL<Ո˺ #PU8\i`X*\Op/x:K 0D:O1/MOQC@ B<qOt d" Q#T;b8Q- < U dOBOJTڬH | ~!ܪ, a-=*5 ZtE9P =6IP.ӕ?M]79Ӱf0a4 %:%8=PReK QmPXϭvU4bI!3ELCS*եLSR' ZBS_ VE^%`=TPuѬ֫|hBĈ`=0i,(GmpSQimn[5W*…h Ws:uPāYMlZPHft*ڸLX1Xl%ؐa q[+ 0? 'i( h0]iY`k;@PP@ Zf  Z=+N23Zڻr `[`l=kh`M@[!2!kQ[Pe@DoMLdX2z]rUVBӎ]Kd .M kӪڦD2ɜ>w /]ڴm:^mU^j^="E 0&tK }a%ܵنX =8цJ;feehq-Nd!Mp)!`ZZ'P`B ƪ!!N|\ p+ah`U[x'b6:b&*b8,)bF <=M΢ȮMIRZX,bRzd ;Ƥe Q1^ADч *aά@d;X0a G%>@dZI҉VR \3 <#hH}EM$9PJ\'B%a>M(čffff f~cWUħ/uKR'&pUMc-X+8 ;vxyZiI$H( HgU6 -4`b@ax8P^fMϬ lL#V}YV(EX=h -|ϮՀhaH<*h&(vi O1  o8oZ(ƓT zӇ 0fp*_v2<pwnez1tSPG{xqq, qLGhrh+rr r."xpwrfZ&s#w ,hTFxfǙyfKLyOʧw-02 _4݂rZPhxMjs|90%/;v3 s0GX{]bM$ % aq菐Gl ny*gqrT&Z)f|z(W؁W|܇_҆Px}A2J Mnޗ}=N=ubA4A q> 4_vhsv+8?8aP'l FdW d.|{jJkݬ6{sNJ88,V`n(rD ą̀| ~Vl$Vmh9,Vl]늁p2떈Rov9KבNغ]/5p=Xa׈b WXf`U{8a9e(8ac0d`n!k W)k|d-pu`ee[b"'#t⑽+#>>qZV%2z%zl,=(c҂5 ɞ؛f6-٫/W:эzVX_.dWf&?ej_`7y y-9W>`ˊVey]2Q:Xٕ^=NW:<{Hhz3ˎ=>{ˎ%t]A`5D86k$^X#HeWRç6|X$]0( JO > )c!\RS(jȷ0W?+wZu=88[pzQu*Wr'j![f),zZ;>.%dcp-b=,2.b[ 70f; ,k*c1`bBAq4+7;EAHJE4vQ i]iyvh^W9ƕ@%]Ƥ:x%i(a5 04Y| C| J i(\ZD8o.Mh(eYPa5{6p!0ehfDO'Al̦,2"hs,aQ@~'T1̘V]8P bg:ۏ JɄغ?0s¤f«#xXxZ⃉ :t˶Q-cr-Uct`|Cb 0l.` 9(0`xCX$```5bX11aG XPIc—a ,.{X 9[Mo˷up$b[jw4fQaTPjT)zep ;+L,pxa6exmZe]m& eaHhX?a*a"σe8:8Nb]pi|%}Om>+",?O֫oC#bhYc[0}σpirc܆Mu;xXR+/8Yp=|v* ZsQ[vX X u (]|2HaQÇ/I8s v3:3,dh āXj/^MQǭu<$֐d W2OZ OqOa`p0Wx[a%z$yM p} ]p#tS< }WUXW2s[a%+K$ aa%w23 8dS2 aRW:@*;pٰa k$sd(#; C]Dx@}t 88[eU1M}( [(YTIxdsr#[H#ax[I%z rx< eL$f} !;x I%y1؄eU^ AI afv},Bz5O'0   m?<Ms+Xa "9rU(S݉-=m]u ,OHG$4ERS$0\t3Uˮš€(x/=(a!:(a_w,Oc($lP0πąx/4AASu?HaӄAǢz允z@R UVMx@"_fd~213ĄČI HHMPEH0 Hy[(qM2"g8xf4idb-gP "nq9n="Hڎ ]lvLU.COM[04/07/91]% @Xc 4fA 3MPDUvEiYvFđ@2,-dIt ٫Pk ^nQPT?M&S5:^LT&fdV,NMzXr }R!2l #Ah3!O+e37Wl=/NlO'`x ' 3E '/3Ed5\H 5=>dF07+^C2x/0xIf dk<&@>'D aI֐JCn}R@)E^+ax &^=>/!z <9SOcK&ѰmH8x`aDd&?920aC!F@e"Ԡ!H"X @@rbp ` a Ç!T0"fa`UW*D2Ӄ`D/Ӈ@ 4,B aiai!B/`p ֘> fA9LA8 {yPfh d`r$@8nlKSx$2`*g@e`nedDa e`Pjo8ue&ta &\cGklfjjHBlGS Ubj}Cɔ/Wb 7uXXHBpa`!@H|8QEz (xs'0e# pBXu ' ;+A!jG0#ѐiH4 |G  k'A)Bh@(J @-z 04P`ŀ`hV 6@;f 4 8ƈ! 00PTk!@#{8e0 4FP#< 0_!1!#004  m3!)c = B2L x,S,a $!@PDH@A.Ô0=tN;$xa :SuJ ΈJx% `0]GhD@wNĨ@Nbk0~ @ H$1D LT9;dbG!NrD0 ØBe sB r 9Hn2P K )@( !L)(T T(4Runں?`Aխa_ 5O #lhAj^kYniqsNv [: ̭`*u,CU~@7bWVu(V(zpQw0ĺa<&p~V0eeSb B+ STޫ  03FX)syxX HV9yfK!Y1f2ˠ;(sz FSN)3(#Dto#Ɛ,mCO; Ю!0 p{B*Y"~L?8y`dfY7 E]3A t ' #-d.rXz'k AMкXsϭpxM%2 1`$)2eA X.WRzKaKp ``k =ݳB*PC(Bs2w1(Zs9EC+3yUCC;XCߘ!?P(f  @U;hz*U wt8rw=s`-FAhav %J?0CpXɌ>`+1G緐N]ۭuμ3C-?gbFhl;flQʂ,$!~o;?7 ߛWn[qNB*|hC'8 G~.#'#`_B/oO)-oP10'c@4!$! I V@TR,PrA`\ ń`@ @ @ rf @³@ \ ` ` +D`Z e'* K   J8 >~ @ "`d` / @ @   ` Z  @  *.nJ$0f'M^ @@  'j" ` !%XVwA>*M80@m+Iw@B;\<2Ȟb2֜һ+:  [-F@.+2;̴N#& B(n`6g01 1as@Bb!]4`-jA<U5;*m2.c$Q%@B_%\n.)r/-,B`:+5!@ 2 ܱ('(K1(@ ¢ <ҋ `?@& ~J.'J$j-tAңТ @  RRCt`XQ .  Ah83$*H2*@ "+lt€6ԀN;T3?IH"8sHH 4aHN0SåJ,aYtPJ BW ~ +JI *ufnhsf@`B xO(*xIrĜk!B T.ԩJ)lzL)犃-88Y8BXxNӇC3V{H+,/BP9CO9M[WzvyBfkA O >: = wb ;b6S>`FJ@z?`|x ~ 0 ِ.R b cvJ 31@SxOVcAэz"Ԋ^,VC|+RZ1LI{5D`PC*z= 7JY y?VcӢ coBZ>i`1 0zK|7s|^s>Zgp)R%-Z٬э50U3jzS55U'Uz`mB5}53(oAvX;GTcX5gRՒ򵇶Y-:5Y~[r:5 /ZOuM\\nBM{MV{/{8 =4%/`ᓘ P Qk0Rkz-8  @ @ yٙ) \5FX"=V `U=W-C1^Mg|k^69 yJ#9jŗ){_X|A|3(%wJAʕ'&{_V{÷n-e33  xW߻A M*@#c랼c@Z?)`W,^^%G!@B %Ϟ];B㡯wҿ\|5;+=u5cB |QMURb*p6<#SY_S׵Rnvo@]n_ʷRa;&Y' S('M>Og<&\*ʠ `ʲ# =o1@ D\}oPϝGqo[h0緻3 -BirB׼ml ŗr$9!Fk?cx; w^8N <!O'0aqJ B~ASugUu"/@?=<8  lсTAP æ#FvK6!n !MX?]pqK^2_K3\r.H>~R"АR*SͯfR-<8_[4 ?-2K`A`" (arB'x5+y;`@0AoҞ t @SH0þ%CHQ:1d`Hlvޡfl,Om`l!jp0! BߧPA@H!\ ` \!@ @A8 ; @IT)e2J^KQHæ" ؛|Bv+aRBx ma@CLoA&6P* ]O{v+WeḾAWmEώD, Wp,;~.X`MpSkX]-0ww*XdR OA+\QM`ܞA_"B3u8V 3`Y}$Ka6A'a RjGՀB@GX gu,AIһ3{:A8`bDMKwB1tq;kj}NhX+R,RfXCr_wI˗cDUtUPPlTkT^w0t'0ajسJ WDQ353X]5-8;W} O`DBL XŠ"Lq{;QK!`.lye>Tyd\e!`La`e_ Hz# :/5#Lc l%=bwBY C|"(7ž^{l!sB\5-uqu6JSi ~AZ8a T`U\;;,c{/IQ,WL۰ [h`{ M3+K%&b TՍ]sdǼW' uxֆ;YQQsO*@ / #c `[=H! >럼U)vPꣳDƝA=a@\"eCO@RLd^N7-+#7O"f;v!_eAnLccH̔A N'0A{:)̜U|Y,W A NchA` @ Ri`P'0&#)mA3> \24P~\Dz)n) 0a+; ͵t`i fM;%F^@t}ؚ[>j`"AuTOR ChcM6a_-P)YSlT!a !a AaR4 Rq%7 B2º#{B+\q$jhR\h#Jh!?ָ񜢔$ 2 j8@@fAaՋwRQw:w(*RbvkQqoY;1kWe dK@& TaK쭬-KI) L:e!ķ>56+K\azX?J BMVJ7P]@LLa^p%4S,!wt),<@v #v" <3\ D:G@":xBvi_)\-,N\#{@xAaXV@@Za '-$qnL!z +;;㠒>!Ja`mSO8P7[bki*z!`+IifhrD9..:X+Rlf 6ar@hnq6A5OJp(:ЈZ'$ ʊ!~ޤO1@#֭!%oK'^d SmHT9ic@m!y4<#|!e+" R(y0av̉su >!hc@v{ @mƔ"$ p) ]K!L^7j7˄,.Gfv7M$ &.(i'$(ø>OjV  ARyb O]b | kV) 1 9ߝǮYBl Z ^"5LmAΈ %R䐢&;4 D!?!BC0(  GOú A=b>!?途AN ?Tu|,Ru fn*@׊}Y4Vn `+^*v6| ꇊ*a\ hʪ "khKu+nû+Er:+i%ᕽH-oifhh `'0avVz+(`k!`3` b+n`uhA7+9"~BX(b'1 ^@B@eՈn ;sA b¹֕.7j;䐫3SbK^Y႓~`dwi |^a"`r@C~a! : ~b(~PRKeIC80#K+ybpٝ~R 3?8b r, F. Q/DD FF.!d`4c!@dUk)@F.,/ . @dB *A[y-Bxs@u2CB b`(1p" BL,,o<08RZ ( >j 䟀(_;oAdd)έ8*~@,RՉ#7@h{NVh}v<"p5. nn"2_@ q/b'C%Drz`4!!oh԰# AޘRD_#_Vy@BpAYP}"56n@c~@r`Vh"$βk^$8aŔ)@"p, @A2I#g .fƾdC\@vIb!lxC] 0A`F{;b @Bs4&HXfP l`I ` [Bs `ln <* Al'1sDΊ@Fk-9R+! l0M.nC)!ҡ`n%n}x@y 3a Pc< <4Y 9("qB4zUuPn<53XNӶ`G"&n:KTQfJRNBqx@AG1Hkl"SE [;|? Sa.V;`# `p/@ho3`FDs`"Q\C; iPfdJ 9gg p'0nWFO7_;`Fbo@R?Ói_;d B 5b)[;|?RrPN-y/cMIGl%J*S6f_H"x`8Ib )EIӶ`FW0M6 L'̯MYg.A~q @D 匩@V hB1 *SD8 㠉UA& "-*@ki`G:<'1LU6|'pa!l kL?s щ9B8-yIW@ZRAJA~Ͼ.!)>F;J".! q@Z@s2l<r`@ i+2(;hM'jWvC89h cːQrs`)@MڼA` @ @. ba^b a`xiᥡ`Bޮx/]HBCr  `lC8fx-n%> vA^ F`/SCڥ;#"vԌ!`CS/` l<4 U]= xaJ1,,CI{ 00a$nPb&{BsmBH!U6hc[&D`P|!oS&Lsmcz^VSH y@"$aI n F;;x*9]trGatJ +G.ĭh!f^6!ҽXaD`jS6^Y>|+K@TPC"bl]Mҵ6a fᲳ) *G'0UusT"`A0AD:nwtS`@Ò`YE2@~V`T '~? !`DY*5a5g\a  " a  @`M<~ ObQ + m40b q  ` RA ˛1n59 gC`p x ` x`tT1TAYTj# 4uGР* yE @ z噹W ? /`ljf:@%Wt@ β\ `TSaA^ t @ˆ` |a@_= Ϭ,a,|\|#,d$@t&duSaAJ , xya@|dpО fC@D>Ѵd^6}F4'0!|@8Tc@{MLSc 4(Avu8V@dpt fz@39=R a`Fxg!;2v+h#+2Y4Ri-H8ta@#` @1, CN*r$P4dhX4 `B1Ff7F4"G "(Z|PTM:R< O K6dDl0!h:6>oN jb zD64e$;VHF,,ݬ ucé\gBޓML-JzsW%zޮA l8*03׏uBV$ISēD?3$HxHA %{0[7uv@h 1ť0 #`> #tYV\{"LMQb4l?(iL S· wB`ħ,*^tG v]bL"I{^cWfU8"}݀RIV'bc(6JJ:)Pc9)HWVRf|u0vFy%Fv<_9Uz( @#4EO`"#C0k^=C6nx0R0EcB <AycX+՛ĦD3@A,:Hv O02B9NPj?Ó6"({x#4G0!(Xdc.9WDu CM4@>d<!,VY A3wi0aHI@9T 2A,>4 L ͣp)8 {0KQ`E mF eeao($^hw04*Cf L#K =D!0"?ddlr7?h `@2@&ԝ@x?(|Ԇ{ELu1| A 7H `bT7821:@ .D@[4N5B2Ad!?&- bS!@G0_*14/xL!%Rl,Qa? rd4K#Mì2A; B>GYkxcA y  ERATOS C FA C "FB C 6FC C $߿FFD C +b9FM C . ISPRINT C ISPUNCT C 9SISSPACE C W,ISUPPER C 5ISXDIGITC HITOA C ITOAB C /ITOD C $ITOO C *ITOU C /pITOX C 5LCC SUB7DLEFT C :aLEXCMP C < LIBID C HAMALLOC C IȯMAX C LMIN C MbcNEWLIB SUBNOTOI C U2OUTP MACXPAD C [QPOLL C ]PRNTF C arPUTCHAR C wȸPUTLIST MACy!\PUTS C ~?:READ C 'RENAME C REVERSE C PREWIND C SIGN C STDIO H STRCAT C STRCHR C STRCMP C STRCPY C W"STRLEN C STRNCAT C STRNCMP C 8STRNCPY C -STRRCHR C ސTIME C HTOASCII C oTOLOWER C rTOPOFMEMMAC<TOUPPER C UALLOC C [ULINK MAC/+,UNGETC C UNLINK MAC*UTOI C WRITE C qXTOI C iZZBUF MACvZZFIO MACB /* ** stdiol.h -- header for resident stdio/crtl/call ** -Set up for Version 2.08 compiler 8/4/84 (fas) */ #define stdin 0 #define stdout 1 #define stderr 2 #define stdport 3 #define stdlist 4 #define ERR -2 #define EOF -1 #define YES 1 #define NO 0 #define TRUE 1 #define FALSE 0 #define NULL 0 #define CR 13 #define LF 10 /* ** return 'true' if c is a printable character ** (32-126) */ isprint(c) int c; { return (c>=32 && c<=126); } #define NOCCARGC /* no argument count passing */ /* ** return 'true' if c is a punctuation character ** (all but control and alphanumeric) */ ispunct(c) int c; { return (!isalnum(c) && !iscntrl(c)); } /* ** return 'true' if c is a white-space character */ isspace(c) int c; { /* first check gives quick exit in most cases */ return(c<=' ' && (c==' ' || (c<=13 && c>=9))); } /* ** return 'true' if c is upper-case alphabetic */ isupper(c) int c; { return (c<='Z' && c>='A'); } /* ** return 'true' if c is a hexadecimal digit ** (0-9, A-F, or a-f) */ isxdigit(c) int c; { return ((c<='f' && c>='a') || (c<='F' && c>='A') || (c<='9' && c>='0')); } #define NOCCARGC /* no argument count passing */ /* ** itoa(n,s) - Convert n to characters in s */ itoa(n, s) char *s; int n; { int sign; char *ptr; ptr = s; if ((sign = n) < 0) /* record sign */ n = -n; /* make n positive */ do { /* generate digits in reverse order */ *ptr++ = n % 10 + '0'; /* get next digit */ } while ((n = n / 10) > 0); /* delete it */ if (sign < 0) *ptr++ = '-'; *ptr = '\0'; reverse(s); } #define NOCCARGC /* no argument count passing */ /* ** itoab(n,s,b) - Convert "unsigned" n to characters in s using base b. ** NOTE: This is a non-standard function. */ itoab(n, s, b) int n; char *s; int b; { char *ptr; int lowbit; ptr = s; b >>= 1; do { lowbit = n & 1; n = (n >> 1) & 32767; *ptr = ((n % b) << 1) + lowbit; if(*ptr < 10) *ptr += '0'; else *ptr += 55; ++ptr; } while(n /= b); *ptr = 0; reverse (s); } #include stdio.h /* ** itod -- convert nbr to signed decimal string of width sz ** right adjusted, blank filled; returns str ** ** if sz > 0 terminate with null byte ** if sz = 0 find end of string ** if sz < 0 use last byte for data */ itod(nbr, str, sz) int nbr; char str[]; int sz; { char sgn; if(nbr<0) {nbr = -nbr; sgn='-';} else sgn=' '; if(sz>0) str[--sz]=NULL; else if(sz<0) sz = -sz; else while(str[sz]!=NULL) ++sz; while(sz) { str[--sz]=(nbr%10+'0'); if((nbr=nbr/10)==0) break; } if(sz) str[--sz]=sgn; while(sz>0) str[--sz]=' '; return str; } /* ** itoo -- converts nbr to octal string of length sz ** right adjusted and blank filled, returns str ** ** if sz > 0 terminate with null byte ** if sz = 0 find end of string ** if sz < 0 use last byte for data */ itoo(nbr, str, sz) int nbr; char str[]; int sz; { int digit; if(sz>0) str[--sz]=0; else if(sz<0) sz = -sz; else while(str[sz]!=0) ++sz; while(sz) { digit=nbr&7; nbr=(nbr>>3)&8191; str[--sz]=digit+48; if(nbr==0) break; } while(sz) str[--sz]=' '; return str; } #include stdio.h /* ** itou -- convert nbr to unsigned decimal string of width sz ** right adjusted, blank filled; returns str ** ** if sz > 0 terminate with null byte ** if sz = 0 find end of string ** if sz < 0 use last byte for data */ itou(nbr, str, sz) int nbr; char str[]; int sz; { int lowbit; if(sz>0) str[--sz]=NULL; else if(sz<0) sz = -sz; else while(str[sz]!=NULL) ++sz; while(sz) { lowbit=nbr&1; nbr=(nbr>>1)&32767; /* divide by 2 */ str[--sz]=((nbr%5)<<1)+lowbit+'0'; if((nbr=nbr/5)==0) break; } while(sz) str[--sz]=' '; return str; } /* ** itox -- converts nbr to hex string of length sz ** right adjusted and blank filled, returns str ** ** if sz > 0 terminate with null byte ** if sz = 0 find end of string ** if sz < 0 use last byte for data */ itox(nbr, str, sz) int nbr; char str[]; int sz; { int digit, offset; if(sz>0) str[--sz]=0; else if(sz<0) sz = -sz; else while(str[sz]!=0) ++sz; while(sz) { digit=nbr&15; nbr=(nbr>>4)&4095; if(digit<10) offset=48; else offset=55; str[--sz]=digit+offset; if(nbr==0) break; } while(sz) str[--sz]=' '; return str; } /* ** left -- left adjust and null terminate a string */ left(str) char *str; { char *str2; str2=str; while(*str2==' ') ++str2; while(*str++ = *str2++); } #define NOCCARGC /* no argument count passing */ /* ** lexcmp(s, t) - Return a number <0, 0, or>0 ** as s is <, =, or > t. */ lexcmp(s, t) char *s, *t; { while(*s == *t) { if(*s == 0) return (0); ++s; ++t; } return (lexorder(*s, *t)); } /* ** lexorder(c1, c2) ** ** Return a negative, zero, or positive number if ** c1 is less than, equal to, or greater than c2, ** based on a lexicographical (dictionary order) ** colating sequence. ** */ char Ulex[128] = { /**** NUL - / ****/ 000,001,002,003,004,005,006,007,008,009, 010,011,012,013,014,015,016,017,018,019, 020,021,022,023,024,025,026,027,028,029, 030,031,032,033,034,035,036,037,038,039, 040,041,042,043,044,045,046,047, /**** 0-9 ****/ 065,066,067,068,069,070,071,072,073,074, /**** : ; < = > ? @ ****/ 048,049,050,051,052,053,054, /**** A-Z ****/ 075,076,077,078,079,080,081,082,083,084,085,086,087, 088,089,090,091,092,093,094,095,096,097,098,099,100, /**** [ \ ] ^ U ` ****/ 055,056,057,058,059,060, /**** a-z ****/ 075,076,077,078,079,080,081,082,083,084,085,086,087, 088,089,090,091,092,093,094,095,096,097,098,099,100, /**** { | } ~ ****/ 061,062,063,064, /**** DEL ****/ 101 }; lexorder(c1, c2) char c1, c2; { return(Ulex[c1] - Ulex[c2]); } #include libid() { puts("\n\n This library created 11/24/84 by F. A. Scacchitti\n\n"); } #define NOCCARGC /* no argument count passing */ #include stdio.h /* ** Memory allocation of size bytes. ** size = Size of the block in bytes. ** Returns the address of the allocated block, ** else NULL for failure. */ malloc(size) char *size; { return (Ualloc(size, NO)); } /* ** max.c by F.A.Scacchitti 9 - 10 - 84 */ max(a,b) int a, b; { if(a > b) return(a); return(b); } /* ** min.c by F.A.Scacchitti 9 - 10 - 84 */ min(a,b) int a, b; { if(a < b) return(a); return(b); } XSUB LIB80 NEWCLIB= ULINK LIBID UNGETC FFLUSH REWIND CTELL CTELLC CSEEK FILELIB FREAD READ FWRITE WRITE GRABUF GRABIO FREBUF FREEIO FPRINTF FSCANF PRNTF FPUTS FGETS GETS PUTS FPUTC FGETC PUTCHAR GETCHAR GETCHX CPMIO CPMDISK PUTLIST CALLOC MALLOC UALLOC AVAIL FREE POLL ABS ATOI ATOIB DTOI ISALNUM ISALPHA ISASCII ISATTY ISCNTRL ISDIGIT ISGRAPH ISLOWER ISPRINT ISPUNCT ISSPACE ISUPPER ISXDIGIT ITOA ITOAB ITOD ITOO ITOU ITOX LEFT LEXCMP OTOI REVERSE SIGN STRCAT STRCHR STRCMP STRCPY STRLEN STRNCAT STRNCMP STRNCPY STRRCHR TOASCII TOLOWER TOUPPER UTOI XTOI PAD FEOF FERROR CLEARERR DELAY DOLDDR DOLDIR INP OUTP TOPOFMEM UNLINK MIN MAX ABORT BDOS CALL1 CALL2 CALL3 CALL4 CALL5 ZZFIO ZZBUF /E A: PIP A:=B:NEWCLIB.REL[v] #include stdio.h /* ** otoi -- convert unsigned octal string to integer nbr ** returns field size, else ERR on error */ otoi(octstr, nbr) char *octstr; int *nbr; { int d,t; d=0; *nbr=0; while((*octstr>='0')&(*octstr<='7')) { t=*nbr; t=(t<<3) + (*octstr++ - '0'); if ((t>=0)&(*nbr<0)) return ERR; d++; *nbr=t; } return d; }  ; outp(port#,data) ; added 2/84 (fas) OUTP:: INX SP ; Skip over return address INX SP POP H ; Load data in L POP B ; Load port # in C DB 0EDH, 069H ; Do instruction PUSH B ; Restore stack PUSH H DCX SP DCX SP ; All gone RET END #define NOCCARGC /* no argument count passing */ /* ** Place n occurrences of ch at dest. */ pad(dest, ch, n) char *dest, *n; int ch; { /* n is a fake unsigned integer */ while(n--) *dest++ = ch; } #define NOCCARGC /* no argument count passing */ #define ABORT 3 #define PAUSE 19 #include stdio.h /* ** Poll for console input or interruption */ poll(pause) int pause; { int i; i = bdos(6,255); if(pause) { if(i == PAUSE) { while(!(i = bdos(6,255))) ; if(i == ABORT) abort(0); return (0); } if(i == ABORT) abort(0); } return (i); }  /* ** prntf("format string"[, arg, arg, ...]) -- formatted print ** operates as described by Kernighan & Ritchie with ** the following exceptions: ** ** - only d, c, and s formats supported ** - maximum field-width specification of 9 ** - no field seperator specification ** ** Modified version of J. E. Hendrix's printf distributed ** with Small-C Version 2.0. This version uses putchar for ** for output and is renamed to prntf to avoid mutiple ** global defines. It is designed to occupy minimum code ** space and can be used interchangeably with printf(),as ** long as the exceptions are taken into consideration. ** ** F. A. Scacchitti 10/7/84 */ #include /* ** Making the following variables static greatly reduces size ** while increasing speed. However, if static globals aren't ** available on your compiler, the prntf.mac file must be ** edited to remove the additional colon generated by the ** compiler to ensure no problems occur with multiple global ** definitions. An alternative to this method would involve ** renaming all the static variable with some little used ** prefix. (eg. qqq, xxx, ppp) */ static int i, width, len, *nxtarg, sz; static char *ctl, *cx, c, right, str[7], *sptr, pad, sgn; prntf(argc) int argc; { i = CCARGC(); /* fetch arg count from A reg first */ nxtarg = &argc + i - 1; ctl = *nxtarg; while(c = *ctl++) { if(c != '%') { putchar(c); continue; } if(*ctl == '%') { putchar(*ctl++); continue; } cx = ctl; right = 1; pad = ' '; if(*cx == '-') { right = 0; ++cx; } if(*cx == '0') { pad = '0'; ++cx; } width = *cx - '0'; if(width < 1 || width >9) width = 0; else cx++; sptr=str; c = *cx++; i = *(--nxtarg); switch(c) { case 'd': sz = 7; if(i < 0) { i = -i; sgn='-'; } else sgn=' '; str[--sz] = NULL; while(sz) { str[--sz] = (i % 10 + '0'); if((i = i / 10) == 0) break; } if(sz) str[--sz] = sgn; while(sz > 0) str[--sz]=' '; break; case 'c': str[0] = i; str[1] = NULL; break; case 's': sptr = i; break; default : continue; } ctl = cx; /* accept conversion spec */ if(c == 'd') while(*sptr==' ') ++sptr; len = -1; while(sptr[++len]); /* get length */ if(right) while(((width--) - len) > 0) putchar(pad); while(len) { putchar(*sptr++); --len; --width; } while(((width--) - len) > 0) putchar(pad); } } #define NOCCARGC /* no argument count passing */ /* * putchar() Normal console output via BDOS(2) */ #include putchar(c) char c; { bdos(2,c); if (c == CR) bdos(2,LF); }  ; ; putlist(c) ; ; F. A. Scacchitti 8/4/84 ; ; CBDOS EQU 5 ;/* bdos entry point */ LF EQU 10 EOL EQU 13 ; ; CP/M BDOS CALLS ; LSTOUT EQU 5 ;write character to list device ; ; Storage varibles found in ulink() or ulinq() ; EXTRN ZZTEMP ; ; PUTLIST:: POP B POP D PUSH D PUSH B SHLD ZZTEMP MVI C,LSTOUT ; cpm(LSTOUT,c); CALL CBDOS ; (mod to cbdos(fas)) LDA ZZTEMP CPI EOL ; if(c==EOL) JNZ PUTLS1 MVI E,LF ; cpm(LSTOUT,LF); MVI C,LSTOUT CALL CBDOS ; (mod to cbdos(fas)) PUTLS1: LHLD ZZTEMP ; return(c & 0377) MVI H,0 RET END #define NOCCARGC /* no argument count passing */ /* *puts(string) Print string to console via BDOS(9) */ puts(string) char *string; { int i; i = 0; while(string[i] != 0){ putchar(string[i]); i++; } } /* ** read.c by F. A. Scacchitti 11/24/84 */ #include extern int zzbuf; read(fd,buffer,cnt) int fd, cnt; char *buffer; { int i, n; char *tbuff, flag; tbuff = &zzbuf; n=0; while(cnt >0){ if((flag = bdos(20,fd)) != NULL) { *(fd + 40) = flag; return(n); }else i = 0; while(i <= 127 && cnt > 0){ buffer[n] = tbuff[i]; i++; cnt--; n++; } } return(n); } /* ** rename(old,new) char *old, *new; by F.A.Scacchitti 9/11/84 */ #define NOCCARGC #include rename(old,new) char *old, *new; { int fcbloc; if ((fcbloc = grabio()) == NULL) return(ERR); fcb(fcbloc, old); fcb(fcbloc + 16, new); freeio(fcbloc); if(bdos(23,fcbloc) >= 0) return(NULL); return(ERR); } #define NOCCARGC /* no argument count passing */ /* ** reverse string in place */ reverse(s) char *s; { char *j; int c; j = s + strlen(s) - 1; while(s < j) { c = *s; *s++ = *j; *j-- = c; } }  /* ** rewind.c by F. A. Scacchitti 9/11/84 */ #define NOCCARGC #include rewind(fd) int fd; { return(cseek(fd, 0, 0)); } /* ** sign -- return -1, 0, +1 depending on the sign of nbr */ sign(nbr) int nbr; { if(nbr>0) return 1; if(nbr==0) return 0; return -1; } /* ** concatenate t to end of s ** s must be large enough */ strcat(s, t) char *s, *t; { char *d; d = s; --s; while (*++s) ; while (*s++ = *t++) ; return(d); } /* ** return pointer to 1st occurrence of c in str, else 0 */ strchr(str, c) char *str, c; { while(*str) { if(*str == c) return (str); ++str; } return (0); } /* ** return <0, 0, >0 aUording to ** st */ strcmp(s, t) char *s, *t; { while(*s == *t) { if(*s == 0) return (0); ++s; ++t; } return (*s - *t); } /* ** copy t to s */ strcpy(s, t) char *s, *t; { char *d; d = s; while (*s++ = *t++) ; return(d); } /* ** return length of s */ strlen(s) char *s; { char *t; t = s - 1; while (*++t) ; return (t - s); } /* ** concatenate n bytes max from t to end of s ** s must be large enough */ strncat(s, t, n) char *s, *t; int n; { char *d; d = s; --s; while(*++s) ; while(n--) { if(*s++ = *t++) continue; return(d); } *s = 0; return(d); } /* ** strncmp(s,t,n) - Compares two strings for at most n ** characters and returns an integer ** >0, =0, or <0 as s is >t, =t, or 0) { if(*d++ = *sour++) continue; while(n-- > 0) *d++ = 0; } *d = 0; return (dest); } /* ** strrchr(s,c) - Search s for rightmost occurrance of c. ** s = Pointer to string to be searched. ** c = Character to search for. ** Returns pointer to rightmost c or NULL. */ strrchr(s, c) char *s, c; { char *ptr; ptr = 0; while(*s) { if(*s==c) ptr = s; ++s; } return (ptr); } /* ** return ASCII equivalent of c */ toascii(c) int c; { return (c); } /* ** return lower-case of c if upper-case, else c */ tolower(c) int c; { if(c<='Z' && c>='A') return (c+32); return (c); } ; ; ; End of memory function ; Returns top memory location in HL CBDOS EQU 5 TOPOFMEM:: LDA CBDOS+2 ; Get base of BDOS (mod to cbdos (fas)) MOV H,A ; Save page in HL MVI L,0 RET END /* ** return upper-case of c if it is lower-case, else c */ toupper(c) int c; { if(c<='z' && c>='a') return (c-32); return (c); }  /* ** ------------ Memory Allocation */ /* ** Allocate n bytes of (possibly zeroed) memory. ** Entry: n = Size of the items in bytes. ** clear = "true" if clearing is desired. ** Returns the address of the allocated block of memory ** or NULL if the requested amount of space is not available. */ #include extern char *zzmem; Ualloc(n, clear) char *n; int clear; { char *oldptr; if(n < avail(YES)) { if(clear) pad(zzmem, NULL, n); oldptr = zzmem; zzmem += n; return (oldptr); } return (NULL); } ; ulink ; ; Small-C System Library Version 1.0 ; ; by ; ; Fred A. Scacchitti ; 25 Glenview Lane ; Roch., NY 14609 ; ; 11 - 24 - 84 ; ; This module is a derivative of RUNTIME.MAC by Glen Fisher ; and Bill Randle. It contains a minimal implementation of ; CP/M hooks to allow proper linking of Small-C programs ; compiled by Version 2.08 (and later) of the Small-C compiler. ; ; This module contains the following routines: ; ; -ULINK entry point just like J. E. Hendrix Vers. 2.1 ; ; -Initialization of stack, memory buffers, and argument ; passing (argv, argc). ; ; ; call to main() ; links to main in user program ; ; -Cleans house and returns to CP/M ; ; ; ; ; Now then here's the starting code ; ; ; ; 1st - Save CPM's stack pointer, establish file i/o constructs set ; new default buffer and establish start of available memory. ; ; 2nd - Get the default disk and set stack at base of BDOS or CCP ; depending on the status ZZZCCP. 0 = bdos 1 = ccp ; ; 3rd - Parse the CPM input line and modify it so that we can pass ; the C program in the argc, argv form that it expects. ; HL = pointer to next argv entry ; DE = pointer to next character in command line ; B = number of characters left in line ; C = argument count (argc) ; ; 4th - Call MAIN to commence operation of the user program ; ; 5th - Work, work, work and then return to here via exit(), abort() ; or normal return from program. ; ; 6th - Close any open files (buffers are not flushed) ; ; 7th - Restore CP/M's stack pointer, select the disk you entered ; with, reset the default buffer and return to CP/M either ; via a JMP 0 (ZZZCCP = 0) or RET (ZZZCCP = 1). ; ; CBDOS EQU 5 ;/* bdos entry point */ CPMARG EQU 128 ;/* CP/M command line */ MAXARG EQU 24 ;/* Maximum number of input args */ STDIN EQU 0 STDOUT EQU 1 STDERR EQU 2 STDLST EQU 4 CBDOS EQU 5 CLOSE EQU 16 ; FCBSIZE EQU 36 ;size, in bytes, of an FCB BUFFER EQU 6 ;offset to disk sector buf. in I/O struct. UNGOT EQU 5 ;offset to char ungotten by ungetc() FLAG EQU 33 ;file-type flag byte (in unused part of FCB) FREEFLG EQU 128 ;This I/O structure is available BUFSIZ EQU 1024 ;how long the sector buffer is NBUFS EQU 8 ;number of I/O buffers TBUFSZ EQU 128 ;size of default disk buffer ; EXTRN MAIN, ZZBUF, ZZZCCP ; ; ULINK:: ; LXI H,0 ; get CPM's stack pointer DAD SP SHLD ZZSTAK ; save it for later ; MVI C,26 LXI D,ZZBUF CALL CBDOS ; Set the default buffer out there ; SETIO: MVI B,NBUFS LXI H,ZZBUF+TBUFSZ+FLAG LXI D,FCBSIZE+BUFFER+BUFSIZ MVI A,FREEFLG SETIO2: MOV M,A ;set all buffers to free DAD D ;on to next buffer DCR B JNZ SETIO2 ;if there is one... SHLD ZZMEM ;put it where it belongs ; MVI C,25 ; get logged-in disk CALL CBDOS INR A STA ZZDFLT ; save it ; LDA CBDOS+2 ; get base of BDOS MOV H,A ; save page in HL MVI L,0 ; where do we put the stack ; LDA ZZZCCP ; let's check ORA A ; JZ SETSTK ; just below the BDOS MOV A,H SUI 8 ; just below the CCP MOV H,A ; SETSTK: SPHL ; set stack pointer ; MVI C,0 ; Init argc LXI H,ARGV ; Pointer to first entry of argv array ; ; CPM does not tell us what the first word of the command ; line was (the name of pgm), so we fake it by pointing it ; to an ascii string with '*' in it ; LXI D,PGM ; Pointer to 'pgmname' string CALL SVARG ; Save next argument ; ; Ok, now for the real stuff. Set DE pair to point to ; CPM command line and start searching for arguments LXI D,CPMARG ; Pointer to CPM arg line LDAX D ; Load # character in line MOV B,A ; Save it in B NXTSP: INX D ; Point to next character DCR B ; Decrement character count JM ENDCMD ; End of cmd line LDAX D ; Load next character in line CPI ' ' ; Space? JZ NXTSP ; Yes...continue searching CALL SVARG ; Nope, save starting point of this arg ; Loop looking for either end of line of a space NXTCH: INX D ; Point to next character DCR B ; Decrement character count JM ENDWRD ; End of cmd line, but need to end arg LDAX D ; Load next character in line CPI ' ' ; Space? JNZ NXTCH ; Nope...keep looking MVI A,0 ; Yes, replace it with a zero byte STAX D JMP NXTSP ; Look for start of next arg ENDWRD: MVI A,0 STAX D ENDCMD: MVI B,0 ; Zero B (BC now is 16 bit argc) PUSH B ; First arg to main procedure LXI H,ARGV ; Point to argv array PUSH H ; Second argument to main procedure MVI A,2 ; Load up the argument count ; CALL MAIN ; Transfer to the C world.... ; ; anchors ; away ; my ; bo ; y ; y ; y ; y ; y ; EXIT:: MVI B,NBUFS ; Prepare to scan for open files MVI C,CLOSE LXI H,ZZBUF+TBUFSZ+FLAG LXI D,FCBSIZE+BUFFER+BUFSIZ SCANEM: MOV A,M ; Get free flag CPI FREEFLG ; Is it free ? JZ NOPEN ; Yes - not open, go get next PUSH B ; No - prepare to close PUSH D PUSH H LXI D,-FLAG DAD D XCHG ; DE --> Start of FCB CALL CBDOS ; Close the file POP H ; Restore scan setup POP D POP B NOPEN: DAD D ; Point to next flag DCR B ; Last one ? JNZ SCANEM ; No - keep scanning until done ; MVI C,26 LXI D,80H CALL CBDOS ; Reset the default buffer ; LHLD ZZSTAK ; Load stack pointer SPHL LDA ZZZCCP ; How do we get back ? ORA A RNZ ; this way to CCP ; ; or ; ; this way to warm boot ; LDA ZZDFLT ; Grab orig. logged-in disk MOV E,A DCR E ; (cvt. back to 0-n) MVI C,14 ; and log it in again CALL CBDOS ; (mod to cbdos (fas)) ; JMP 0 ; ; SVARG: MOV M,E ; Save pointer to start of string INX H MOV M,D INX H INR C ; Increment argc RET PGM: DB '*',0 ; ARGV: DS MAXARG*2 ; ZZDFLT:: DB 0 ; default disk ; ZZSTAK:: DW 0 ; CP/M's stack ; ZZMEM:: DW 0 ; useable memory pointer ; ZZTEMP:: DW 0 ; available to anyone ; ; ; END ULINK  /* ** ungetc.c by fas 8/30/84 */ #include #define FCBSIZE 36 #define UNGOT 5 ungetc(c,fd) char c, *fd;{ if(fd[FCBSIZE+UNGOT] != EOF) return(EOF); fd[FCBSIZE+UNGOT] = c; return(c); } ; ; unlink(name) ; UNLINK:: DELETE:: POP B POP D PUSH D PUSH B PUSH D ; name ; /* open file to unlink in LXI H,"r" ; Mode ; order to get fcb for it. */ PUSH H CALL FOPEN ; unit = fopen(name,'r'); POP D POP D SHLD UNIT MVI C,19 ; bdos(19,unit); CALL BDOS ; (mod to cbdos(fas)) LHLD UNIT ; freeio(unit); PUSH H CALL FREEIO POP D RET ; return; UNIT: DS 2 EXTRN BDOS EXTRN FOPEN EXTRN FREEIO END ;#include stdio.h /* ** utoi -- convert unsigned decimal string to integer nbr ** returns field size, else ERR on error */ utoi(decstr, nbr) char *decstr; int *nbr; { int d,t; d=0; *nbr=0; while((*decstr>='0')&(*decstr<='9')) { t=*nbr;t=(10*t) + (*decstr++ - '0'); if ((t>=0)&(*nbr<0)) return ERR; d++; *nbr=t; } return d; } /* ** write.c by F. A. Scacchitti 11/24/84 */ #include extern int zzbuf; write(fd,buffer,cnt) int fd, cnt; char *buffer; { int i, n; char *tbuff, flag; tbuff = &zzbuf; n = fd + 33; /* prevents fcb buffer flush */ *n = NULL; n=0; while(cnt >0){ i = 0; while(i <= 127 && cnt > 0){ tbuff[i] = buffer[n]; i++; cnt--; n++; } if((flag = bdos(21,fd)) != NULL) { *(fd + 40) = flag; return(n); } } return(n); } #include stdio.h /* ** xtoi -- convert hex string to integer nbr ** returns field size, else ERR on error */ xtoi(hexstr, nbr) char *hexstr; int *nbr; { int d,t; d=0; *nbr=0; while(1) { if((*hexstr>='0')&(*hexstr<='9')) t=48; else if((*hexstr>='A')&(*hexstr<='F')) t=55; else if((*hexstr>='a')&(*hexstr<='f')) t=87; else break; if(d<4) ++d; else return ERR; *nbr=*nbr<<4; *nbr=*nbr+(*hexstr++)-t; } return d; } ; ; ZZBUF.MAC by F. A. Scacchitti 9-18-84 ; ; Default Buffer for disk I/O ; ; Used to preserve standard CP/M buffer for input arguments ; and mark the end of the code space. ; ZZBUF:: NOP END  ; File i/o storage varibles ; ; ZZUNIT:: DS 2 ;I/O structure address to act on ZZIP:: DS 2 ;int *ZZIP; ZZCHP:: DS 2 ;char *ZZCHP; ZZDP:: DS 2 ;char *ZZDP; ZZFILE:: DS 2 ;file name ZZMODE:: DS 2 ;char *mode;(read or write) ZZCH:: DS 2 ;char ch; ZZT:: DS 2 ;int t; ZZFN:: DS 2 ;int ZZFN; i/o function (for cpmio) ZZNUBU:: DS 2 ;# TEMPORARY BUFFER STORAGE ZZMXSC:: DS 1 ;# SECTOR COUNTER ZZSVCH:: DS 2 ;char *ZZSVCH; saved character pointer END /* ** time.c Time set/display Program by F.A.Scacchitti 9/23/84 ** Copyright 1984 25 Glenview Lane ** All rights reserved Roch, NY 14609 ** ** Written in Small-C (Version 2.09) ** ** Time Utility for the Xerox 820 ** ** time p ---> prints current time and date ** time s ---> enter time set routine ** ** This program is designed to be used with an auxiliary printf routine ** (prntf) to minimize program size. (printf may be substituted for prntf) ** (fas) ** */ #include #define CLEAR 26 #define BACKSP 8 #define SPACE 32 #define VERTAB 11 #define LINSIZ 18 /*#define MEM 65369 pointer to first time byte for the 820-I */ #define MEM 65366 /* pointer to first time byte for the 820-II */ char array[LINSIZ]; int num[6]; int lolim[] = { 1, 1, 84, 0, 0, 0}; int hilim[] = {31, 12, 99, 23, 59, 59}; main(argc,argv) int argc, *argv; { char *entry; argv++; /* point to option */ entry = *argv; /* set up 2nd indirect pointer *entry = **argv */ switch (*entry) { case 'P': if(!gudtim(gettim())) settim(); if(gudtim()) prntim(); break; case 'S': if(settim()) prntim(); break; default: argc = 0; break; } if (argc != 2){ prntf(" usage: time p prints time and date\n"); prntf(" time s to set time and date\n"); } } prntim(){ /* Routine to print time and date */ char *clkmem; putchar(VERTAB); clkmem = MEM; clkmem++; switch (*clkmem){ case 1: prntf("January"); break; case 2: prntf("February"); break; case 3: prntf("March"); break; case 4: prntf("April"); break; case 5: prntf("May"); break; case 6: prntf("June"); break; case 7: prntf("July"); break; case 8: prntf("August"); break; case 9: prntf("September"); break; case 10: prntf("October"); break; case 11: prntf("November"); break; case 12: prntf("December"); break; default: abort('?'); } clkmem--; prntf(" %d, 19%d %02d:%02d:%02d",*clkmem++,*++clkmem,*++clkmem, *++clkmem,*++clkmem); } settim(){ /* Routine to set time and date */ int i; char c, *clkmem; clkmem = MEM; /* Display the time set header */ putchar(CLEAR); prntf("Enter the time and date as dd/mm/yy hh:mm:ss\n"); prntf("\n eg. for 1:45 P.M. on August 12, 1984\n"); prntf(" Enter ---> 12/08/84 13:45:00\n"); prntf(" dd/mm/yy hh:mm:ss"); prntf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); /* Get the input string */ i = -1; while (((c = getchar()) != CR) && i++ < 17) if (c == BACKSP) if (i == 0){ i = -1; putchar(SPACE);} else i = i - 2; else array[i] = c; /* Convert the characters to integer values */ for (i = 0; i <= 18; i = i + 3) num[i/3] = ((array[i] - '0') * 10) + (array[i+1] - '0'); prntf("\n\n"); /* Store the values to memory if they're valid */ if (gudtim()) { for (i = 0; i <=5; i++) *clkmem++ = num[i]; return(TRUE); }else{ prntf(" Incorrect data entered - time not updated"); return(FALSE); } } gudtim(){ int i; for(i = 0; i <= 5;i++) if (num[i] < lolim[i] || num[i] > hilim[i]) return(FALSE); return(TRUE); } gettim(){ /* Routine to get time data from memory to an array */ int i; char *clkmem; clkmem = MEM; for (i = 0; i <=5; i++) num[i] = *clkmem++; } /* Eratosthenes Sieve Prime Number Program in C */ /* Uses local (automatic) Variables */ #include #define SIZE 8190 #define SIZEP1 8191 char flags[SIZEP1]; main() { int i, prime, k, count, iter; /* variables defined here are local */ printf("10 iterations :"); for (iter = 1; iter<=10; iter ++) { count = 0; for (i = 0; i<= SIZE; i++) flags[i] = TRUE; for (i = 0; i<= SIZE; i++) { if (flags[i]) { prime = i + i + 3; k = i + prime; while (k <= SIZE) { flags [k] = FALSE; k += prime; } count = count + 1; } } } printf(" %d primes", count); }  /* ** fa.c File Append Program by F.A.Scacchitti 9/23/84 ** ** Written in Small-C Version 2.09 or later ** ** Appends one files on to another ** ** printf may be substituted for prntf (fas) */ #include int fdin, fdin2; main(argc,argv) int argc, argv[]; { int fdin, fdin2; char c; if (argc != 3) { prntf("\nfa usage: fa \n"); exit(); } if((fdin = fopen(argv[1],"a")) == NULL) { prntf("\nUnable to open file %s\n",argv[1]); exit(); } if((fdin2 = fopen(argv[2],"r")) == NULL) { prntf("\nUnable to create file %s.\n",argv[2]); exit(); } while((c = fgetc(fdin2)) != EOF) fputc(c,fdin); fclose(fdin); fclose(fdin2); } /* ** fb.c File Copy (Bin) Program by F.A.Scacchitti 9/23/84 ** ** Written in Small-C Version 2.09 or later ** ** Copies file from file to file ** Byte modifications may be made during transfer */ #include #define BUFSIZE 8192 main(argc,argv) int argc, argv[]; { int fdin, fdout; /* file i/o channel pointers */ int i, count; char *inbuf; i = 0; inbuf = malloc(BUFSIZE); if(argc != 3) { puts("\nfc usage: fc \n"); exit(); } if((fdin = fopen(argv[1],"r")) == NULL) { puts("\nUnable to open input file.\n"); exit(); } if((fdout = fopen(argv[2],"w")) == NULL) { puts("\nUnable to create output file.\n"); exit(); } while((count = read(fdin,inbuf,BUFSIZE)) == BUFSIZE) { write(fdout,inbuf,count); i += count; } i += count; write(fdout,inbuf,count); fclose(fdin); fclose(fdout); } /* ** fc.c File Copy Program by F.A.Scacchitti 9/23/84 ** ** Written in Small-C Version 2.09 or later ** ** Copies file from file to file ** Byte modifications may be made during transfer ** ** printf may be substituted for prntf (fas) ** */ #include main(argc,argv) int argc, argv[]; { int fdin, fdout; /* file i/o channel pointers */ char c; if (argc != 3) { prntf("\nfc usage: fc \n"); exit(); } if((fdin = fopen(argv[1],"r")) == NULL) { prntf("\nUnable to open file %s\n",argv[1]); exit(); } if((fdout = fopen(argv[2],"w")) == NULL) { prntf("\nUnable to create file %s.\n",argv[2]); exit(); } while((c = fgetc(fdin)) != EOF) /* ** Here's where we can modify the file */ fputc(c,fdout); fclose(fdin); fclose(fdout); } /* ** ffd.c formfeed Program by F.A.Scacchitti 11/26/84 ** Copyright 1984 25 Glenview Lane ** All rights reserved Roch, NY 14609 ** ** Written in Small-C (Version 2.10) ** ** ** ** ** ** */ #include int i; main() { for(i = 1; i <= 66; i++) putlist(LF); } /* ** fm.c File Modification Program by F.A.Scacchitti 9/23/84 ** ** Written in Small-C Version 2.09 or later ** ** Copies from source file to new file modifying on the fly. ** Mod. description is in modify routine. ** ** This program may be used as a shell for any ascii file ** modification utilities. */ #include int fdin, fdout; /* file i/o channel pointers */ char c; /* the byte we're modifying */ main(argc,argv) int argc, argv[]; { if (argc != 3) { puts("\nfm usage: fm \n"); exit(); } if((fdin = fopen(argv[1],"r")) == NULL) { puts("\nUnable to open input file\n"); exit(); } if((fdout = fopen(argv[2],"w")) == NULL) { puts("\nUnable to create output file\n"); exit(); } while((c = fgetc(fdin)) != EOF) /* ** Here's where we modify the file */ fputc((modify(c)),fdout); fclose(fdin); fclose(fdout); } /* this routine double spaces an ascii file */ modify(c) char c; { if( c == CR) { fputc(CR,fdout); return(LF); }else return(c); }  cc -a -p -l2 $1.c >$1.mac m80 $1=$1 l80 $1,$2,$3,$4,$5,$6,$7,$8,$9,clib/s,$1/n/e  [ABORT MACABS C  ATOI C 4kATOIB C oAVAIL C xBDOS MAC CALL1 MAC%1CALL2 MAC+CALL3 MAC9CALL4 MACA91CALL5 MACF.eECALLOC C tWCLEARERRC w>{CLIB DOCyt CLIB LST CPMDISK MAC(CPMIO MACCSEEK C  [CTELL C CTELLC C #jDELAY MAC%d(DOLDDR MAC+4DOLDIR MAC.4DTOI C 1]EXIT MAC5FEOF C 9"FERROR C ;FFLUSH C =oFGETC MACB#jFGETS MACejFILELIB MAC|JeFPRINTF C FPUTC MACEFPUTS MACFREAD C FREBUF C FREE C `IFREEIO MACFSCANF C  FWRITE C -C2GETCHAR C /GETCHX C 1GETS MAC3DGRABIO MACFGRABUF C NsINP MACPG1ISALNUM C S|ISALPHA C UISASCII C VISATTY C XuISCNTRL C ZԀISDIGIT C \ISGRAPH C ]AISLOWER C ^vISPRINT C _ISPUNCT C `9SISSPACE C bW,ISUPPER C d5ISXDIGITC eHITOA C gITOAB C k/ ; ; abort.mac by F. A. Scacchitti 11 - 24 - 84 ; ; abort(error code) ; EXTRN EXIT ; ABORT:: ; POP B ; throw away return address POP H ; get abort code ORA A ; code passed ? JZ ABORT2 ; no - leave it as is MOV A,L STA ABCODE ; yes - imbed it in the message ABORT2: LXI D,ABTMSG ; Load abort message MVI C,9 CALL 5 JMP EXIT ; ABTMSG: DB 0DH, 'Aborted ' ; ABCODE: DB 07,0D,'$' ; END /* ** abs -- returns absolute value of nbr */ abs(nbr) int nbr; { if(nbr < 0) return (-nbr); return (nbr); } #define NOCCARGC /* no argument count passing */ /* ** atoi(s) - convert s to integer. */ atoi(s) char *s; { int sign, n; while(isspace(*s)) ++s; sign = 1; switch(*s) { case '-': sign = -1; case '+': ++s; } n = 0; while(isdigit(*s)) n = 10 * n + *s++ - '0'; return (sign * n); } #define NOCCARGC /* no argument count passing */ /* ** atoib(s,b) - Convert s to "unsigned" integer in base b. ** NOTE: This is a non-standard function. */ atoib(s, b) char *s; int b; { int n, digit; n = 0; while(isspace(*s)) ++s; while((digit = (127 & *s++)) >= '0') { if(digit >= 'a') digit -= 87; else if(digit >= 'A') digit -= 55; else digit -= '0'; if(digit >= b) break; n = b * n + digit; } return (n); } #define NOCCARGC /* no argument count passing */ /* ** Return the number of bytes of available memory. ** In case of a stack overflow condition, if 'abort' ** is non-zero the program aborts with an 'S' clue, ** otherwise zero is returned. */ external char *zzmem avail(aburt) int aburt; { char x; if(&x < zzmem) { if(aburt) abort('M'); return (0); } return (&x - zzmem); } ; ; bdos.mac by F. A. Scacchitti 9 - 18 - 84 ; ; This assembly routine allows CPM calls from Small C. ; ; bdos(function,data) or cpm(function,data) ; ; NOTE - This function only returns what the bdos call ; placed in the accumulator ; BDOS:: ; CPM:: ; POP H ; Pop rtn address POP D ; Pop input parameter in DE register pair POP B ; Pop function code into C register PUSH B ; Restore stack PUSH D PUSH H CALL 5 MOV L,A ; Sign extend A into HL register pair RLC SBB A MOV H,A ; RET ; END  ;----- call1.mac Small-C arithmetic and logical library ; ; part 1 Multiply Routine ; ; ; ; ;MULTIPLY DE BY HL AND RETURN IN HL ;(SIGNED MULTIPLY) ; CCMULT:: MULT: MOV B,H MOV C,L LXI H,0 CCMLT1: MOV A,C RRC JNC CCMLT2 DAD D CCMLT2: XRA A MOV A,B RAR MOV B,A MOV A,C RAR MOV C,A ORA B RZ XRA A MOV A,E RAL MOV E,A MOV A,D RAL MOV D,A ORA E RZ JMP CCMLT1 END ; ;----- call2.mac Small-C arithmetic and logical library ; ; ; part 2 divide routine ; ; ;DIVIDE DE BY HL AND RETURN QUOTIENT IN HL, REMAINDER IN DE ;(SIGNED DIVIDE) ; CCDIV:: DIV: MOV B,H MOV C,L MOV A,D XRA B PUSH PSW MOV A,D ORA A CM CCDENEG MOV A,B ORA A CM CCBCNEG MVI A,16 PUSH PSW XCHG LXI D,0 CCDIV1: DAD H CALL CCRDEL JZ CCDIV2 CALL CCCMPBCDE JM CCDIV2 MOV A,L ORI 1 MOV L,A MOV A,E SUB C MOV E,A MOV A,D SBB B MOV D,A CCDIV2: POP PSW DCR A JZ CCDIV3 PUSH PSW JMP CCDIV1 CCDIV3: POP PSW RP CALL CCDENEG XCHG CALL CCDENEG XCHG RET ; ;NEGATE THE INTEGER IN DE ;(INTERNAL ROUTINE) ; CCDENEG: MOV A,D CMA MOV D,A MOV A,E CMA MOV E,A INX D RET ; ;NEGATE THE INTEGER IN BC ;(INTERNAL ROUTINE) ; CCBCNEG: MOV A,B CMA MOV B,A MOV A,C CMA MOV C,A INX B RET ; ;ROTATE DE LEFT ONE BIT ;(INTERNAL ROUTINE) ; CCRDEL: MOV A,E RAL MOV E,A MOV A,D RAL MOV D,A ORA E RET ; ;COMPARE BC TO DE ;(INTERNAL ROUTINE) ; CCCMPBCDE: MOV A,E SUB C MOV A,D SBB B RET END ; ;----- call3.mac Small-C arithmetic and logical library ; ; ; part 3 switch routine ; ; ; EXECUTE "SWITCH" STATEMENT ; ; HL = SWITCH VALUE ; (SP) -> SWITCH TABLE ; DW ADDR1, VALUE1 ; DW ADDR2, VALUE2 ; ... ; DW 0 ; [JMP default] ; continuation ; CCSWITCH:: XCHG ;;DE = SWITCH VALUE POP H ;;HL -> SWITCH TABLE SWLOOP: MOV C,M INX H MOV B,M ;;BC -> CASE ADDR, ELSE 0 INX H MOV A,B ORA C JZ SWEND ;;DEFAULT OR CONTINUATION CODE MOV A,M INX H CMP E MOV A,M INX H JNZ SWLOOP CMP D JNZ SWLOOP MOV H,B ;;CASE MATCHED MOV L,C SWEND: PCHL END  ; ;----- call4.mac Small-C arithmetic and logical library ; ; ; part 4 arithmetic shift routines ; ; ;SHIFT DE ARITHMETICALLY RIGHT BY HL AND RETURN IN HL ; CCASR:: XCHG DCR E RM MOV A,H RAL MOV A,H RAR MOV H,A MOV A,L RAR MOV L,A JMP CCASR+1 ; ;SHIFT DE ARITHMETICALLY LEFT BY HL AND RETURN IN HL ; CCASL:: XCHG DCR E RM DAD H JMP CCASL+1 ; END  ; ;----- call5.mac Small-C arithmetic and logical library ; ; ; part 5 main routine - multiply, divide, switch and ; shift routines in seperate modules ; CCDCAL:: PCHL CCDDGC:: DAD D JMP CCGCHAR ; CCDSGC:: INX H INX H DAD SP ; ;FETCH A SINGLE BYTE FROM THE ADDRESS IN HL AND ;SIGN EXTEND INTO HL ; CCGCHAR:: MOV A,M ; ;PUT THE ACCUM INTO HL AND SIGN EXTEND THROUGH H. ; CCARGC:: CCSXT:: MOV L,A RLC SBB A MOV H,A RET ; CCDDGI:: DAD D JMP CCGINT ; CCDSGI:: INX H INX H DAD SP ; ;FETCH A FULL 16-BIT INTEGER FROM THE ADDRESS IN HL ;INTO HL ; CCGINT:: MOV A,M INX H MOV H,M MOV L,A RET ; CCDECC:: INX H INX H DAD SP MOV D,H MOV E,L CALL CCGCHAR DCX H MOV A,L STAX D RET ; CCINCC:: INX H INX H DAD SP MOV D,H MOV E,L CALL CCGCHAR INX H MOV A,L STAX D RET ; ; ; CCDDPC:: CDPDPC:: ; DAD D CCPDPC:: POP B ;;RET ADDR POP D PUSH B ; ;STORE A SINGLE BYTE FROM HL AT THE ADDRESS IN DE ; CCPCHAR:: PCHAR:: MOV A,L STAX D RET ; CCDECI:: INX H INX H DAD SP MOV D,H MOV E,L CALL CCGINT DCX H JMP CCPINT ; CCINCI:: INX H INX H DAD SP MOV D,H MOV E,L CALL CCGINT INX H JMP CCPINT ; ; ; CCDDPI:: CDPDPI:: ; DAD D CCPDPI:: POP B ;;RET ADDR POP D PUSH B ; ;STORE A 16-BIT INTEGER IN HL AT THE ADDRESS IN DE ; CCPINT:: PINT:: MOV A,L STAX D INX D MOV A,H STAX D RET ; ;INCLUSIVE "OR" HL AND DE INTO HL ; CCOR:: MOV A,L ORA E MOV L,A MOV A,H ORA D MOV H,A RET ; ;EXCLUSIVE "OR" HL AND DE INTO HL ; CCXOR:: MOV A,L XRA E MOV L,A MOV A,H XRA D MOV H,A RET ; ;"AND" HL AND DE INTO HL ; CCAND:: MOV A,L ANA E MOV L,A MOV A,H ANA D MOV H,A RET ; ;IN ALL THE FOLLOWING COMPARE ROUTINES, HL IS SET TO 1 IF THE ;CONDITION IS TRUE, OTHERWISE IT IS SET TO 0 (ZERO). ; ;TEST IF HL = DE ; CCEQ:: CALL CCCMP RZ DCX H RET ; ;TEST IF DE <> HL ; CCNE:: CALL CCCMP RNZ DCX H RET ; ;TEST IF DE > HL (SIGNED) ; CCGT:: XCHG CALL CCCMP RC DCX H RET ; ;TEST IF DE <= HL (SIGNED) ; CCLE:: CALL CCCMP RZ RC DCX H RET ; ;TEST IF DE >= HL (SIGNED) ; CCGE:: CALL CCCMP RNC DCX H RET ; ;TEST IF DE < HL (SIGNED) ; CCLT:: CALL CCCMP RC DCX H RET ; ;COMMON ROUTINE TO PERFORM A SIGNED COMPARE ; OF DE AND HL ;THIS ROUTINE PERFORMS DE - HL AND SETS THE CONDITIONS: ; CARRY REFLECTS SIGN OF DIFFERENCE (SET MEANS DE < HL) ; ZERO/NON-ZERO SET ACCORDING TO EQUALITY. ; CCCMP:: MOV A,H ;;INVERT SIGN OF HL XRI 80H MOV H,A MOV A,D ;;INVERT SIGN OF DE XRI 80H CMP H ;;COMPARE MSBS JNZ CCCMP1 ;;DONE IF NEQ MOV A,E ;;COMPARE LSBS CMP L CCCMP1: LXI H,1 ;;PRESET TRUE COND RET ; ;TEST IF DE >= HL (UNSIGNED) ; CCUGE:: CALL CCUCMP RNC DCX H RET ; ;TEST IF DE < HL (UNSIGNED) ; CCULT:: CALL CCUCMP RC DCX H RET ; ;TEST IF DE > HL (UNSIGNED) ; CCUGT:: XCHG CALL CCUCMP RC DCX H RET ; ;TEST IF DE <= HL (UNSIGNED) ; CCULE:: CALL CCUCMP RZ RC DCX H RET ; ;COMMON ROUTINE TO PERFORM UNSIGNED COMPARE ;CARRY SET IF DE < HL ;ZERO/NONZERO SET ACCORDINGLY ; CCUCMP:: MOV A,D CMP H JNZ CCUCP1 MOV A,E CMP L CCUCP1: LXI H,1 RET ; ;SUBTRACT HL FROM DE AND RETURN IN HL ; CCSUB:: MOV A,E SUB L MOV L,A MOV A,D SBB H MOV H,A RET ; ;FORM THE TWO'S COMPLEMENT OF HL ; CCNEG:: CALL CCCOM INX H RET ; ;FORM THE ONE'S COMPLEMENT OF HL ; CCCOM:: MOV A,H CMA MOV H,A MOV A,L CMA MOV L,A RET CCLNEG:: MOV A,H ORA L JNZ $+6 MVI L,1 RET LXI H,0 RET ; ; END #define NOCCARGC /* no argument count passing */ #include stdio.h /* ** Cleared-memory allocation of n items of size bytes. ** n = Number of items to allocate space for. ** size = Size of the items in bytes. ** Returns the address of the allocated block, ** else NULL for failure. */ calloc(n, size) char *n, *size; { return (Ualloc(n*size, YES)); } /* ** clearerr.c by F. A. Scacchitti 11/22/84 ** ** Clears errors and end of file marks in fd. ** */ #include clearerr(fd) int fd; { *(fd + 40) = NULL; }  CLIB.DOC by F. A. Scacchitti 25 Glenview Lane Rochester, NY 14609 11 - 24 - 84 Thi 'C Librar contain mos o th function describe i J E Hendrix' "Th Small- Handbook" Thes function ar als describe i th Ma 198 Dr Dobb' Journal M intent a i his i t provid complet standar librar followin specication describe i "Th à Programmin Language" Thi librar i combinatio o module obtaine fro Hendrix' library modifie publi domai runtim librar an module writte b myself Th followin sourc file contai th function describe i thi document: ABORT .MAC ABS .C ATOI .C ATOIB .C AVAIL .C BDOS .MAC CALL1 .MAC CALL2 .MAC CALL3 .MAC CALL4 .MAC CALL5. .MAC CALLOC .C CLEARERR.C CPMDISK .MAC CPMIO .MAC CSEEK .C CTELL .C CTELLC .C DELAY .MAC DOLDDR .MAC DOLDIR .MAC DTOI .C FEOF .C FERROR .C FFLUSH .C FGETC .MAC FGETS .MAC FILELIB .C FPRINTF .C FPUTC .MAC FPUTS .MAC FREAD .C FREBUF .C FREE .C FREEIO .MAC FSCANF .C FWRITE .C GETCHAR .C GETCHX .C GETS .MAC GRABIO .MAC GRABUF .C INP .MAC ISALNUM .C ISALPHA .C ISASCII .C ISATTY .C ISCNTRL .C ISDIGIT .C ISGRAPH .C ISLOWER .C ISPRINT .C ISPUNCT .C ISSPACE .C ISUPPER .C ISXDIGIT.C ITOA .C ITOAB .C ITOD .C ITOO .C ITOU .C ITOX .C LEFT .C LEXCMP .C LIBID .C MALLOC .C MAX .C MIN .C OTOI .C OUTP .MAC PAD .C POLL .C PRNTF .C PUTCHAR .C PUTLIST .MAC PUTS .C READ .C RENAME .C REVERSE .C REWIND .C SIGN .C STRCAT .C STRCHR .C STRCMP .C STRCPY .C STRLEN .C STRNCAT .C STRNCMP .C STRNCPY .C STRRCHR .C TOASCII .C TOLOWER .C TOPOFMEM.MAC TOUPPER .C UALLOC .C ULINK .C UNGETC .C UNLINK .MAC UTOI .C WRITE .C XTOI .C ZZBUF .MAC ZZFIO .MAC Rathe tha tryin t provid Unix-lik environmen (an th resultin overhead) I'v attempte t pu packag togethe whic i mor conduciv to CP/M Thi Librar i designe t produc minimu siz file whil retainin th flavo o 'C' Man o th function ar writte i assemble and a tim permits mor function wil b optimize fo bot siz an speed Mos function containe i thi librar ar useabl wit an CP/ 8 system however man o th I/ function interac wit eac othe a wel a th runtim routines Anyon adaptin an portion o thi librar shoul evaluat th sourc cod o th particula module(s i question A wit al libraries its valu manifest itsel whe use wit linking-loade tha ha searc capabilities (eg Microsoft M80/L80/LIB8 package) .pa FEATURES OF THE LIBRARY 104 function (5 aliases ar available includin mos standar 'C functions. Smalle progra siz tha mos - minimu progra siz i 25 bytes. This would be the result of the following 'C' code. #include main() { } Arg an arg ar handle b th runtim modul an alway passe t th use program maximu o 2 argument ma b passe wit 23 availabl t the user. File ma b opene i read writ o appen modes Read/writ (+ mode ar no supported. All I/O buffers are allocated outside program space including: 1 128 byte default disk I/O buffer 8 1 K byte file buffers (available for general use) Th defaul dis I/ buffe i se b th runtim modul t preserv th content o th ru strin residin a th CP/ defaul buffer Th standar defaul buffe (80h i restore a progra completion. Th堠 fil buffer ar automaticall allocate䠠 an deallocate b th fil handlin routine an th use needn' worr abou sequence However thes buffer ar no restricte t fil I/O The ma b allocate vi th grabuf( functio an deallocate vi frebuf() Cautio mus b use t insur tha an us o thes buffer doe no excee th K-byt limit Th result o failin t sta withi th limit i unpredictable. Sequentia젠 dynami㠠 memor allocation/deallocatio schem (calloc,malloc an free start a th en o th las buffe an end a th stack Th use mus maintai th integrit o thi area I buffe i se fre belo on tha shoul b maintained, th schem wil indicat al memor abov an includin th release buffe i available Allocatin an usin anothe buffe a thi poin ma undesirabl wip ou dat whic should have been maintained. Optionall eliminat th war boo tha occur o progra termination Thi i accomplishe in the following manner: Definin th globa ZZZCC place th stac a th bas o th BDO an return vi war boo. (jmp 0) Definin th globa ZZZCC place th stac a th bas o th CC an return t th CCP. ZZZCC ma b generate a compile functio vi switch o adde a th followin inlin cod t progra o heade file. #asm zzzccp:: db 1 #endasm I lef undefine i wil defaul t war boot Th linke wil indicat i a undefined wit n consequence CP/͠ integrit i maintaine b th runtim modul an restore a progra completion Also al ope file ar closed bu buffers are NOT flushed. prntf( i specia versio o print whic onl support th d c an specifications Fiel lengt specifier (whe used ar limite t siz o an fiel separato specification aren' allowe an shoul no b used Thi modul occupie 82 byte o cod space. getchx( i specia versio o getchar( whic use direc consol inpu rathe tha th standar consol input I doe no reflec character t th scree o tra th CP/͠ contro characters. grabuf( an frebuf( allo th use acces t sel managin memor allocatio scheme Eac buffe returne b grabuf( i 1 byte o memor an shoul no b exceeded Althoug thi isn' standard i doe provid somewha bom resistan (no proof memory alloc./dealloc. schema along with the standards. .pa FUNCTIONS IN THE LIBRARY Onl th function no describe i J E Hendrix' Small- Manua, or those that differ from his, wil b described. abort(code) exit th progra displayin th "Aborted messag an optiona cod passe b th user I n cod i passe default code of control g (bell) is used. abs(nbr) int nbr atoi(str) char *str atoib(str,base) char *str; int base; avail(abort) int abort; bdos(fn,data) int fn, data; standar CP/ bdo cal f i th functio cod an dat i th settin o th d register Return whateve th cal places in the accumulator. calloc(nbr,sz) int nbr, sz; cfree(addr) char *addr; clearerr(fd) int fd; cpm(fn,data) same as bdos(fn,data) cpmdisk(nbr) int nbr; log in disk number nbr. cseek(fd,offset,mode) ctell(fd) int fd; ctellc(fd) int fd; delay(n) int n; dela fo millisecond, base o Mh cloc (25 nanosecon cycl time). delete(name) char *name; dolddr(source, destination, n) int source, destination, n; perform z80 lddr instruction. doldir(source, destination, n) int source, destination, n; perform z80 ldir instruction dtoi(decstr, nbr) char *decstr; int nbr; exit(code) exit(); exits program and returns to CP/M fcb(fd,name) char *name; int fd; construct a file fcb on file name at location fd. (located in filelib module) fclose(fd) int fd; (located in file lib module) feof(fd) int fd; ferror(fd) int fd; fflush(fd) int fd; fgetc(fd) int fd; fgets(str, sz, fd) char *str; int sz, fd; fopen(filename, mode) char *name, mode; (locate i fileli modul - onl r w an mode ) fprintf(fd, format[, arg1, ar2,...]) int fd; char *format; fputc(c, fd) char c; int fd; fputs(str, fd) char *str; int fd; fread(buffer, sz, n, fd) char *buffer; int fd, n, sz; frebuf(buff) int buff; fre th buffe buf allocate b grabuf( an mak i available for use. free(addr) same as cfree(addr) freeio(fd) int fd; fre th fil structur allocate b grabio( an mak i available for use. fscanf(fd, format, arg, arg, . . . ) fwrite(buff, sz, n, fd) char *buf; int sz, n, fd; getc(fd) same as fgetc(fd) getchar() getchx( i specia versio o getchar( whic use direc consol inpu rathe tha th standar consol input I doe no reflec character t th scree o tra th CP/͠ contro characters. gets(str) char *str; grabio() return th addres o th firs availabl fil堠 I/ structure. If none is available NULL is returned. grabuf() return th addres o th firs availabl buffe i th file I/O structure. If none is available NULL is returned. inp(nbr) int nbr; returns the value read in at port nbr isalnum(c) char c; isalpha(c) char c; isascii(c) char c; isatty(fd) int fd; iscntrl(c) char c; isdigit(c) char c; isgraph(c) char c; islower(c) char c; isprint(c) char c; ispunct(c) char c; isspace(c) char c; isupper(c) char c; isxdigit(c) char c; itoa(nbr, str) int nbr; char *str; itoab(nbr, str, base) int nbr, base; char *str; itod(nbr, str, sz) int nbr,sz; char *str; itoo(nbr,str,sz) int nbr,sz; char *str; itou(nbr,str,sz) int nbr,sz; char *str; itox(nbr,str,sz) int nbr,sz; char *str; left(str) char *str; lexcmp(str1, str2) char *str1, *str2; libid() displays the date and originator of this library malloc(sz) int sz; max(a, b) int a, b; returns the greater of a or b min(a, b) int a, b; returns the lesser of a or b otoi(str,nbr) char *str; int nbr; outp(nbr,data) int nbr, data; transmits data out of port nbr. pad(dest, ch, n) char *dest, *n; int ch; poll(pause) int pause; printf(format[,arg1,arg2,...]) prntf(format[,arg1,arg2,...]) i specia versio o print whic onl support th d c an specifications Fiel lengt specifier (whe used ar堠 limite䠠 t siz o an䠠 fiel䠠 separato specification aren' allowe an shoul no b used putc(c, fd) same as fputc(c, fd) putchar(c) char c; putlist(c) char c; outputs character c to the list device. puts(str) char *str; read(fd, buff, n) int fd, n; char *buff rename(old,new) char *old, *new; reverse(str) char *str; rewind(fd) int fd; scanf(format, arg1, arg2, . . .) sign(nbr) int nbr; strcat(dest, sour) char *dest, *sour; strchr(str, c) char *str, c; strcmp(str1, str2) char *str1, *str2; strcpy(dest, sour) char *dest, *sour; strlen(str) char *str; strncat(dest, sour, n) char *dest, *sour; int n; strncmp(str1, str2, n) char *str1, *str2; int n; strncpy(dest, sour, n) char *dest, *sour; int n; strrchr(str, c) char *str, c; toascii(c) char c; tolower(c) char c; topofmem() returns base of system bdos toupper(c) char c; ualloc(n, clear) char *n; int clear; ungetc(c, fd) char c; int fd; unlink(name) same as delete(name) utoi(str, nbr) char *str; int nbr; write(fd,buffer,n) int fd, n; char *buffer; xtoi()(str, nbr) char *str; int nbr; .pa LIBRARY STRUCTURE Th clib.re Small-C syste librar module ar loade i th followin sequenc t avoi backwar referencin b L80: ULINK** LIBID* UNGETC RENAME FREAD READ FWRITE WRITE FFLUSH REWIND CSEEK CTELL CTELLC FILELIB GRABUF* GRABIO* FREBUF* FREEIO* FPRINTF FSCANF PRNTF* FPUTS FGETS GETS PUTS FPUTC FGETC PUTCHAR GETCHAR GETCHX* CPMIO* CPMDISK* PUTLIST* CALLOC MALLOC UALLOC* AVAIL* FREE POLL* ABS ATOI ATOIB DTOI ISALNUM ISALPHA ISASCII ISATTY ISCNTRL ISDIGIT ISGRAPH ISLOWER ISPRINT ISPUNCT ISSPACE ISUPPER ISXDIGIT ITOA ITOAB ITOD ITOO ITOU ITOX LEFT LEXCMP OTOI REVERSE SIGN STRCAT STRCHR STRCMP STRCPY STRLEN STRNCAT STRNCMP STRNCPY STRRCHR TOASCII TOLOWER TOUPPER UTOI XTOI PAD FEOF FERROR CLEARERR DELAY* DOLDDR* DOLDIR* INP* OUTP* TOPOFMEM* UNLINK MIN* MAX* CALL1** CALL2** CALL3** CALL4** CALL5** BDOS* ABORT ZZFIO** ZZBUF** * indicates a non standard function ** indicates a system function SYSTEM MODULES Refe t th sourc file o thes module fo mor detail regarding operation. ULINˠ (25 bytes contain th routine t stee th 'C progra fro CP/ t th use progra an bac agai t CP/M Thi modul i th onl on i th librar t hav a entr poin define a startin point therefor th progra wil alway star here CALL (3 bytes contain th cod t suppor th multipl operator. ( * ) CALL (9 bytes contain th cod t suppor th divid and modulus operators. ( / % ) CALL (2 bytes contain th cod t suppor th switc statement. CALL (2 bytes contain th cod t suppor th righ an lef shif operators. ( >> << ) CALL (23 bytes contain th cod t suppor al othe arithmeti an logica operator a wel a memor an addres fetch and store operations. ZZFIϠ (23 bytes contain storag fo globa variable use b file I/O and fgetc, fputc, etc . . . ZZBUƠ ( byte i th las modul i th librar an serve t mar th startin poin fo I/ buffer an th dynami memor allocation scheme.  #ABS.C #ATOI.C #ATOIB.C #AVAIL.C #BDOS.MAC #CALL1.MAC #CALL2.MAC #CALL3.MAC #CALL4.MAC #CALL5.MAC #CALLOC.C #CPMDISK.MAC #CPMIO.MAC #CSEEK.C #CTELL.C #CTELLC.C #DELAY.MAC #DOLDDR.MAC #DOLDIR.MAC #DTOI.C #EXIT.MAC #FFLUSH.C #FGETC.MAC #FGETS.MAC #FILELIB.MAC #FPRINTF.C #FPUTC.MAC #FPUTS.MAC #FREAD.C #FREBUF.C #FREE.C #FREEIO.MAC #FSCANF.C #FWRITE.C #GETCHAR.C #GETCHX.C #GETS.MAC #GRABIO.MAC #GRABUF.C #INP.MAC #ISALNUM.C #ISALPHA.C #ISASCII.C #ISATTY.C #ISCNTRL.C #ISDIGIT.C #ISGRAPH.C #ISLOWER.C #ISPRINT.C #ISPUNCT.C #ISSPACE.C #ISUPPER.C #ISXDIGIT.C #ITOA.C #ITOAB.C #ITOD.C #ITOO.C #ITOU.C #ITOX.C #LEFT.C #LEXCMP.C #LIBID.C #MALLOC.C #MAX.C #MIN.C #OTOI.C #OUTP.MAC #PAD.C #POLL.C #PRNTF.C #PUTCHAR.C #PUTLIST.MAC #PUTS.C #READ.C #RENAME.C #REVERSE.C #REWIND.C #SIGN.C #STRCAT.C #STRCHR.C #STRCMP.C #STRCPY.C #STRLEN.C #STRNCAT.C #STRNCMP.C #STRNCPY.C #STRRCHR.C #TOASCII.C #TOLOWER.C #TOPOFMEM.MAC #TOUPPER.C #UALLOC.C #ULINK.MAC #UNGETC.C #UNLINK.MAC #UTOI.C #WRITE.C #XTOI.C #ZZBUF.MAC #ZZFIO.MAC ; ; cpmdisk(disk) ; ; F. A. Scacchitti 8/4/84 ; CBDOS EQU 5 ;/* bdos entry point */ LF EQU 10 EOL EQU 13 ; ; CP/M BDOS CALLS ; SELECT EQU 14 ;log-in a drive ; ; CPMDISK:: POP D POP H PUSH H PUSH D MOV A,L ; if(d~=0) ORA H JZ DISKIF1 XCHG ; cpm(SELECT,d-1); DCX D MVI C,SELECT CALL CBDOS ; (mod fas) DISKIF1: RET END ; ; cpmio(fn,unit) ; ; F. A. Scacchitti 9/4/84 ; CBDOS EQU 5 ;/* bdos entry point */ CPMARG EQU 128 ;/* CP/M command line */ MAXARG EQU 32 ;/* Maximum number of input args */ STDIN EQU 0 STDOUT EQU 1 STDERR EQU 2 STDLST EQU 4 CTRLZ EQU 26 ;control z NULL EQU 0 ;pointer to nothing FCBSIZE EQU 36 ;size, in bytes, of an FCB NEXTP EQU 0 ;offset to next-character pointer in I/O structure UNUSED EQU 2 ;offset to unused-positions-count in I/O structure BUFFER EQU 6 ;offset to disk sector buffer in I/O structure UNGOT EQU 5 ;offset to char ungotten by ungetc() FLAG EQU 33 ;file-type flag byte (in unused part of FCB) FREEFLG EQU 128 ;This I/O structure is available for the taking EOFFLG EQU 2 ;The end of this file has been hit WRTFLG EQU 1 ;This file open for writing BUFSIZ EQU 1024 ;how long the sector buffer is NBUFS EQU 8 ;number of I/O buffers TBUFF EQU 128 ;default cpm buffer LF EQU 10 EOL EQU 13 ; ; CP/M BDOS CALLS ; CLOSE EQU 16 ;close a file CPMSTR EQU 9 ;print '$' delimited string on console CREATE EQU 22 ;make a file DMA EQU 26 ;set DMA (I/O address) DELETE EQU 19 ;delete a file GETCH EQU 1 ;read character from console GETSTR EQU 10 ;read string from console LSTOUT EQU 5 ;write character to list device OPEN EQU 15 ;open a file PUTCH EQU 2 ;write character to console QUERY EQU 25 ;get logged-in drive id READ EQU 20 ;read a sector SELECT EQU 14 ;log-in a drive WRITE EQU 21 ;write a sector ; ; File i/o storage varibles found in ulink() ; EXTRN ZZUNIT EXTRN ZZIP EXTRN ZZCHP EXTRN ZZDP EXTRN ZZFILE EXTRN ZZMODE EXTRN ZZCH EXTRN ZZT EXTRN ZZFN EXTRN ZZNUBU EXTRN ZZMXSC ; ; Characteristics variable storage found in ulink() ; EXTRN ZZSVCH EXTRN ZZDFLT EXTRN ZZSTAK EXTRN ZZMEM ; EXTRN CPMDISK ; ; Default disk I/O buffer ; EXTRN ZZBUF ; CPMIO:: POP B POP D POP H SHLD ZZFN XCHG SHLD ZZUNIT PUSH D PUSH H PUSH B LHLD ZZUNIT ; cpmdisk(*unit); MOV L,M MVI H,0 PUSH H CALL CPMDISK POP H LHLD ZZUNIT ; ZZIP = unit+FCBSIZE; LXI D,FCBSIZE ; cpm(DMA,&ZZIP[BUFFER]); DAD D LXI D,BUFFER DAD D SHLD ZZNUBU ;# SAVE TO UPGRADE DURING LOOPING XCHG MVI C,DMA CALL CBDOS ; (mod fas) LHLD ZZFN ; t = cpm(ZZFN,unit); MOV C,L MVI A,8 ;# READ/WRITE UP TO 8 SECTORS STA ZZMXSC ;# SAVE IT LHLD ZZUNIT XCHG IOLOOP: PUSH H ;# NEW CONSTRUCT TO ACCOMODATE 1K BUFFERS PUSH D ;# SAVE IT ALL FOR REPEAT PERFORMANCE PUSH B ; PUSH H ;# DON'T WRITE BLANKS MOV A,C CPI READ POP H JZ NOWRIT PUSH H LHLD ZZNUBU MOV A,M POP H CPI 1AH ;# END OF FILE CHAR ? JZ IOEXIT ; NOWRIT: CALL CBDOS ;# READ/WRITE A SECTOR PUSH PSW CALL CCSXT## SHLD ZZT POP PSW ORA A ;# CHECK FOR LAST SECTOR JNZ IOEXIT ;# IF LAST GET OUT OF HERE LDA ZZMXSC DCR A ;# CHECK FOR 8 SECTORS DONE JZ IOEXIT STA ZZMXSC LHLD ZZNUBU ;# GET BUFFER ADDRESS LXI D,128 DAD D ;# COMPUTE NEW BUFFER ADDRESS SHLD ZZNUBU ;# SAVE TIL NEXT TIME XCHG MVI C,DMA CALL CBDOS ;# SET THE NEW BUFFER POP B POP D POP H JMP IOLOOP IOEXIT: POP B ;# CLEAN UP POP D POP H MVI C,DMA ; cpm(DMA,ZZBUF); LXI D,ZZBUF CALL CBDOS ; (mod fas) LHLD ZZT ; if(t~=0) return(-1); MOV A,H ; else return(0); ORA L JNZ CPMIF1 LXI H,0 JMP CPMIF2 CPMIF1: LXI H,-1 CPMIF2: RET ; END #include stdio.h /* ** cseek(fd,offset,base) by F.A.Scacchitti 9/15/84 ** ** Position fd to the 128-byte record indicated by ** "offset" relative to the point indicated by "base." ** ** BASE OFFSET-RELATIVE-TO ** 0 first record ** 1 current record ** 2 end of file (last record + 1) ** ** Returns NULL on success, else EOF. */ extern char zzmxsc; char zzzext, zzzrec; cseek(fd, offset, base) int fd, offset, base; { char *fcbdata; int tempofs, unused; fcbdata = fd; switch (base) { case 0: getval(offset); break; case 1: tempofs = gettof(fcbdata); if(tempofs >= 8) tempofs -= (8 - zzmxsc); getval(tempofs + offset); break; case 2: while(bdos(20, fd) == NULL); tempofs = gettof(fcbdata); getval(tempofs - offset); break; default: return (EOF); } fcbdata[12] = zzzext; fcbdata[32] = zzzrec; if(fcbdata[33] != 1){ fcbdata[33] = 0; if(cpmio(20,fd) == EOF); if(zzmxsc == 8) return(EOF); unused = 1024 - (zzmxsc * 128); }else{ unused = 0; } *(fd + 38) = unused; *(fd + 36) = fd + 42; return (NULL); } getval(offset) int offset;{ zzzext = offset / 80; zzzrec = offset % 80; } gettof(fcbdata) char *fcbdata; { int tempofs; return(fcbdata[12] * 80 + fcbdata[32]); }  /* ** ctell.c by F. A. Scacchitti 9/11/84 */ #define NOCCARGC #include ctell(fd) int fd; { char *fcb; int bsec, osec, t; fcb = fd; bsec = (*(fd + 36) - fd - 42) / 128 ; t = fcb[32]; if((osec = t % 8) == 0 && t != 0) osec = 8; if(t < 0) t = 128; return((fcb[12] * 128) + t - osec + bsec); }  /* ** ctellc.c by F. A. Scacchitti 9/11/84 */ #define NOCCARGC #include ctellc(fd) int fd; { return(( *(fd + 36) - fd - 42) % 128 ); } ; ; delay(n) ; int n; ; ; n = number of milliseconds to delay ; DELAY:: POP H ; Return address POP D ; Delay Value PUSH D ; Restore Stack PUSH H ; DELAY1: ;# 51 (overhead) 12.5 usec. LXI B,123 ;# 10 CALL DELAY2 ;# 3963 (17 + 10 + (123 X 32)) DCX D ;# 5 MOV A,D ;# 5 ORA E ;# 4 JNZ DELAY1 ;# 10 RET ;-------- ; 3997 cycles @ 250 nanosec per ; --------------------------- ; 0.99925 milliseconds ; ; ; Delay Loop set for 10 usec. per count based on 4 MHz clock ; DELAY2: DCX B ;# 5 ORA A ;# 4 ORA A ;# 4 MOV A,B ;# 5 ORA C ;# 4 JNZ DELAY2 ;# 10 RET ;# ;#------ ;# 32 cycles @ 250 nanosec per = 12.5 usec. END  ; lddr(source, dest, n) DOLDDR:: INX SP ; Skip over return address INX SP POP B ; Load n POP D ; Load destination POP H ; Load source DB 0EDH, 0B8H ; Do LDDR instruction PUSH H ; Restore stack PUSH D PUSH B DCX SP DCX SP RET END  ; doldir(source, dest, n) DOLDIR:: INX SP ; Skip over return address INX SP POP B ; Load n POP D ; Load destination POP H ; Load source DB 0EDH, 0B0H ; Do LDIR instruction PUSH H ; Restore stack PUSH D PUSH B DCX SP DCX SP RET END #define NOCCARGC /* no argument count passing */ #include stdio.h /* ** dtoi -- convert signed decimal string to integer nbr ** returns field length, else ERR on error */ dtoi(decstr, nbr) char *decstr; int *nbr; { int len, s; if((*decstr)=='-') {s=1; ++decstr;} else s=0; if((len=utoi(decstr, nbr))<0) return ERR; if(*nbr<0) return ERR; if(s) {*nbr = -*nbr; return ++len;} else return len; } ; exit.mac by F. A. Scacchitti 9 - 18 - 84 ; ; abort(error code) ; ; EXTRN ZZFINI ; EXIT:: ; ABORT:: ; POP B ; throw away return address POP H ; get abort code ORA A ; code passed ? JZ ABORT2 ; no - leave it as is MOV A,L STA ABCODE ; yes - imbed it in the message ABORT2: LXI D,ABTMSG ; Load abort message MVI C,9 CALL 5 JMP ZZFINI ; ABTMSG: DB 0DH, 'Aborted ' ; ABCODE: DB 07,0D,'$' ; END /* ** feof.c by F. A. Scacchitti 11/22/84 ** ** Returns true only if end of file is reached. ** */ #include feof(fd) int fd; { char c; c = *(fd + 40); return(c == EOF ? TRUE : FALSE); } /* ** ferror.c by F. A. Scacchitti 11/22/84 ** ** Returns true only if a file error has occurred. ** */ #include ferror(fd) int fd; { char c; c = *(fd + 40); return(c == EOF ? FALSE : c); }  /* ** fflush.c by F. A. Scacchitti 9/15/84 */ #define WRITE 1 #define OPEN 15 #include fflush(fd) int fd; { int unused, charptr; char mode, record, extent; mode = *(fd + 33); if(mode != WRITE) return(NULL); charptr = *(fd + 36); unused = *(fd + 38); extent = *(fd + 12); record = *(fd + 32); if(fclose(fd) != NULL || bdos(OPEN,fd) < NULL) return(EOF); *(fd + 36) = charptr; *(fd + 38) = unused; *(fd + 12) = extent; *(fd + 32) = record; *(fd + 33) = mode; return(NULL); } ; ; ; fgetc(unit) by F. A. Scacchitti 11 - 24 - 84 ; ; getc(unit) ; ; CBDOS EQU 5 ;/* bdos entry point */ CPMARG EQU 128 ;/* CP/M command line */ MAXARG EQU 32 ;/* Maximum number of input args */ STDIN EQU 0 STDOUT EQU 1 STDERR EQU 2 STDLST EQU 4 CTRLZ EQU 26 ;control z NULL EQU 0 ;pointer to nothing FCBSIZE EQU 36 ;size, in bytes, of an FCB NEXTP EQU 0 ;offset to next-char. pointer in I/O struct. UNUSED EQU 2 ;offset to unused-pos.-count in I/O struct. BUFFER EQU 6 ;offset to disk sector buf. in I/O struct. UNGOT EQU 5 ;offset to char ungotten by ungetc() FLAG EQU 33 ;file-type flag byte (in unused part of FCB) FREEFLG EQU 128 ;This I/O structure is available for the taking EOF EQU 0FFH ;# END OF FILE BYTE FOR UNGOTTEN CHAR ID EOFFLG EQU 2 ;The end of this file has been hit WRTFLG EQU 1 ;This file open for writing BUFSIZ EQU 1024 ;how long the sector buffer is NBUFS EQU 8 ;number of I/O buffers TBUFF EQU 128 ;default cpm buffer LF EQU 10 EOL EQU 13 ; ; CP/M BDOS CALLS ; CLOSE EQU 16 ;close a file CPMSTR EQU 9 ;print '$' delimited string on console CREATE EQU 22 ;make a file DMA EQU 26 ;set DMA (I/O address) DELETE EQU 19 ;delete a file GETCH EQU 1 ;read character from console GETSTR EQU 10 ;read string from console LSTOUT EQU 5 ;write character to list device OPEN EQU 15 ;open a file PUTCH EQU 2 ;write character to console QUERY EQU 25 ;get logged-in drive id READ EQU 20 ;read a sector SELECT EQU 14 ;log-in a drive WRITE EQU 21 ;write a sector ; ; File i/o storage varibles found in ulink() ; EXTRN ZZUNIT EXTRN ZZIP EXTRN ZZCHP EXTRN ZZDP EXTRN ZZFILE EXTRN ZZMODE EXTRN ZZCH EXTRN ZZT EXTRN ZZFN EXTRN ZZNUBU EXTRN ZZMXSC ; ; Characteristics variable storage found in ulink() ; EXTRN ZZSVCH EXTRN ZZDFLT EXTRN ZZSTAK EXTRN ZZMEM ; EXTRN GETCHAR EXTRN CPMIO ; FGETC:: GETC:: POP B POP H ; get args PUSH H PUSH B ; c=cget(unit); PUSH H CALL CGET POP D MOV A,L ; if(c=='\r') ANI 7FH ; /* mask parity in compare */ CPI EOL JNZ GETCRET PUSH H ; cget(unit); PUSH D ; /* to skip LF */ CALL CGET POP H POP H GETCRET: RET ; ; cget(unit) ; CGET:: POP D POP H PUSH H PUSH D MOV A,H ORA A ; if(unit < 256) { JNZ CGET1 ; /* assume stdin */ CALL GETCHAR ; getchar(); POP D ;/* return to caller of getc() POP D ; to bypass CR check */ RET ; return; } CGET1: SHLD ZZUNIT LXI D,FLAG ; if(unit[FLAG] & EOF_FL) DAD D MOV A,M ANI EOFFLG JZ GTCIF1 LXI H,-1 ; return(-1); RET GTCIF1: LHLD ZZUNIT ; ip = unit + FCBSIZE; LXI D,FCBSIZE DAD D SHLD ZZIP ; LXI D,UNGOT ;# CHECK FOR UNGOTTEN CHAR. DAD D MOV A,M CPI EOF ;# IS IT EOF ? JZ GTCCON ;# YES-CONTINUE WITH FGETC MOV B,A ;# NO-LET'S GET THE UNGOTTEN MVI A,EOF MOV M,A ;# PUT IN EOF TO MARK IT CLEAR MOV L,B MOV H,0 RET ;# RETURN WITH CHAR IN HL ; GTCCON: LHLD ZZIP LXI D,NEXTP ; cp = ip[NEXTP]; DAD D MOV E,M INX H MOV D,M XCHG SHLD ZZCHP LHLD ZZIP ; if(ip[UNUSED]==0){ LXI D,UNUSED DAD D MOV A,M INX H ORA M JNZ GTCIF2 ; ; Mark beginning of each 128 byte segment of buffer with EOF to ; eliminate possible bogus read ; LHLD ZZUNIT LXI D,FCBSIZE + 4 ; UNIT + FCBSIZE DAD D LXI D,128 MVI B,8 MVI A,1AH SETEOF: MOV M,A DAD D DCR B JNZ SETEOF ; LXI H,READ ;if(cpmio(READ,unit)~=0) PUSH H LHLD ZZUNIT PUSH H CALL CPMIO POP D POP D MOV A,H ORA L JZ GTCIF3 LDA ZZMXSC ;# IS THIS THE FIRST READ CPI 8 ;# JNZ GTCIF3 ;#NO,THERE'S CHARS IN THAT BUF. ;# YES, GETOUTAHERE LXI H,-1 ; return(-1); RET GTCIF3: LHLD ZZIP ;else { ip[UNUSED] = BUFSIZ; LXI D,UNUSED DAD D LXI D,BUFSIZ MOV M,E INX H MOV M,D LHLD ZZIP ; cp = &ip[BUFFER]; LXI D,BUFFER DAD D SHLD ZZCHP ; } ;} GTCIF2: LHLD ZZIP ; ip[UNUSED]--; LXI D,UNUSED DAD D MOV E,M INX H MOV D,M DCX D MOV M,D DCX H MOV M,E LHLD ZZCHP ; ip[NEXTP] = cp+1; INX H XCHG LHLD ZZIP LXI B,NEXTP DAD B MOV M,E INX H MOV M,D LHLD ZZCHP ; if(*cp==CTRL_Z){ MOV A,M ANI 7FH ; /* mask parity */ CPI CTRLZ JNZ GTCIF4 LHLD ZZUNIT ;unit[FLAG] |= EOF_FL; LXI D,FLAG DAD D MOV A,M ORI EOFFLG MOV M,A LXI H,-1 ; return(-1); RET ; } GTCIF4: MOV A,M MOV L,A ; return(*cp & 0377); MVI H,0 RET END  ; ; fgets(cp,len,unit) ; ; CBDOS EQU 5 ;/* bdos entry point */ CPMARG EQU 128 ;/* CP/M command line */ MAXARG EQU 32 ;/* Maximum number of input args */ STDIN EQU 0 STDOUT EQU 1 STDERR EQU 2 STDLST EQU 4 CTRLZ EQU 26 ;control z NULL EQU 0 ;pointer to nothing FCBSIZE EQU 36 ;size, in bytes, of an FCB NEXTP EQU 0 ;offset to next-character pointer in I/O structure UNUSED EQU 2 ;offset to unused-positions-count in I/O structure BUFFER EQU 6 ;offset to disk sector buffer in I/O structure UNGOT EQU 5 ;offset to char ungotten by ungetc() FLAG EQU 33 ;file-type flag byte (in unused part of FCB) FREEFLG EQU 128 ;This I/O structure is available for the taking EOFFLG EQU 2 ;The end of this file has been hit WRTFLG EQU 1 ;This file open for writing BUFSIZ EQU 1024 ;how long the sector buffer is NBUFS EQU 8 ;number of I/O buffers TBUFF EQU 128 ;default cpm buffer LF EQU 10 EOL EQU 13 ; ; CP/M BDOS CALLS ; CLOSE EQU 16 ;close a file CPMSTR EQU 9 ;print '$' delimited string on console CREATE EQU 22 ;make a file DMA EQU 26 ;set DMA (I/O address) DELETE EQU 19 ;delete a file GETCH EQU 1 ;read character from console GETSTR EQU 10 ;read string from console LSTOUT EQU 5 ;write character to list device OPEN EQU 15 ;open a file PUTCH EQU 2 ;write character to console QUERY EQU 25 ;get logged-in drive id READ EQU 20 ;read a sector SELECT EQU 14 ;log-in a drive WRITE EQU 21 ;write a sector ; ; File i/o storage varibles found in ulink() ; EXTRN ZZUNIT EXTRN ZZIP EXTRN ZZCHP EXTRN ZZDP EXTRN ZZFILE EXTRN ZZMODE EXTRN ZZCH EXTRN ZZT EXTRN ZZFN EXTRN ZZNUBU EXTRN ZZMXSC ; ; Characteristics variable storage found in ulink() ; EXTRN ZZSVCH EXTRN ZZDFLT EXTRN ZZSTAK EXTRN ZZMEM ; EXTRN GETC EXTRN GETS ; FGETS:: INX SP ; skip rtn addr INX SP POP B ; unit POP D ; length POP H ; cp PUSH H PUSH D PUSH B DCX SP DCX SP MOV A,B ; if(unit < 256) { ORA A ; /* assume stdin */ JNZ FGETS1 PUSH H CALL GETS ; gets(cp) POP B ; return (cp); RET ; } else { FGETS1: SHLD ZZSVCH ; save_cp = cp; PUSH D ; keep stack right FGETS2: POP D DCX D ; while (--len) { PUSH D MOV A,D ORA E JZ FGETS4 PUSH H ; save cp PUSH B ; unit CALL GETC ; c = getc(unit); POP B MOV A,H ; if(c==EOF) /* c>255 */ ORA A JZ FGETS3 POP D ; cp LHLD ZZSVCH ; if (cp<>save_cp) XCHG ; /* read something */ MOV A,H CMP D JNZ FGETS4 ; goto fgets4; MOV A,L CMP E JNZ FGETS4 ; else LXI H,0 ; /* no characters */ POP D ; fix stack RET ; return (NULL); FGETS3: MOV A,L ; else { POP H MOV M,A ; *cp++ = c; INX H ANI 7FH ; /* mask parity in compare */ CPI LF ; if(c=='\n') JNZ FGETS2 FGETS4: MVI M,0 ; *cp='\0'; POP D ; fix stack LHLD ZZSVCH ; return save_cp; RET ; } } } } END FGETS ; filelib.mac ; ; Small-C File Library Version 1.0 ; ; by ; ; Fred A. Scacchitti ; 25 Glenview Lane ; Roch., NY 14609 ; ; 11 - 24 - 84 ; ; This module is a derivative of RUNTIME.MAC by Glen Fisher ; and Bill Randle. It contains the constructs necessary for ; handling file i/o for C programs compiled by Version 2.08 ; (and later) of the Small-C compiler. ; ; This module contains the following routines: ; ; fopen(name,mode) ; ; fclose(name) ; ; fcb() ; ; fcbpad() ; ; fcbsize() ; ; ; Now then here's the file i/o code ; CBDOS EQU 5 ;/* bdos entry point */ CPMARG EQU 128 ;/* CP/M command line */ MAXARG EQU 32 ;/* Maximum number of input args */ STDIN EQU 0 STDOUT EQU 1 STDERR EQU 2 STDLST EQU 4 CTRLZ EQU 26 ;control z NULL EQU 0 ;pointer to nothing FCBSIZE EQU 36 ;size, in bytes, of an FCB NEXTP EQU 0 ;offset to next-char. pointer in I/O struct. UNUSED EQU 2 ;offset to unused-pos.-count in I/O struct. BUFFER EQU 6 ;offset to disk sector buf. in I/O struct. UNGOT EQU 5 ;offset to char ungotten by ungetc() FLAG EQU 33 ;file-type flag byte (in unused part of FCB) FREEFLG EQU 128 ;This I/O structure is available EOF EQU 0FFH EOFFLG EQU 2 ;The end of this file has been hit WRTFLG EQU 1 ;This file open for writing BUFSIZ EQU 1024 ;how long the sector buffer is NBUFS EQU 8 ;number of I/O buffers TBUFF EQU 128 ;default cpm buffer LF EQU 10 EOL EQU 13 ; ; CP/M BDOS CALLS ; CLOSE EQU 16 ;close a file CPMSTR EQU 9 ;print '$' delimited string on console CREATE EQU 22 ;make a file DMA EQU 26 ;set DMA (I/O address) DELETE EQU 19 ;delete a file GETCH EQU 1 ;read character from console GETSTR EQU 10 ;read string from console LSTOUT EQU 5 ;write character to list device OPEN EQU 15 ;open a file PUTCH EQU 2 ;write character to console QUERY EQU 25 ;get logged-in drive id READ EQU 20 ;read a sector SELECT EQU 14 ;log-in a drive WRITE EQU 21 ;write a sector ; ; ; File i/o storage varibles found in ZZFIO.MAC ; ; EXTRN ZZUNIT EXTRN ZZIP EXTRN ZZCHP EXTRN ZZDP EXTRN ZZFILE EXTRN ZZMODE EXTRN ZZCH EXTRN ZZT EXTRN ZZFN EXTRN ZZNUBU EXTRN ZZMXSC EXTRN ZZSVCH ; ; ; ; Characteristics variable storage found in ulink() ; ; EXTRN ZZDFLT EXTRN ZZSTAK EXTRN ZZMEM EXTRN ZZTEMP ; ; Start of file buffers found at end of program ; EXTRN GRABIO EXTRN FREEIO EXTRN CPMIO EXTRN CPMDISK ; ; Required to set buffer in append mode ; EXTRN PUTC ; ; Default disk I/O buffer ; EXTRN ZZBUF ; ; Storage variables used by append mode ; CURREC: DB 0 CUREXT: DB 0 OLDREC: DB 0 OLDEXT: DB 0 ; ; fopen(name,mode) ; FOPEN:: ; POP B ;get args POP H ;mode SHLD ZZMODE POP D XCHG SHLD ZZFILE PUSH H PUSH D PUSH B CALL GRABIO ; unit = grabio(); SHLD ZZUNIT MOV A,H ; if(unit==NULL) ORA L ; return(NULL); RZ LXI D,FCBSIZE ; ZZIP = unit+FCBSIZE; DAD D SHLD ZZIP ; LXI D,UNGOT ;# OFFSET TO UNGOTTEN CHAR DAD D MVI M,0FFH ;# EOF TO AVOID EXTRA CHAR ; DCX H ;# POINT TO ERROR BYTE MVI M,0 ;# CLEAR IT ; LHLD ZZIP ;ZZIP[NEXTP]=&ZZIP[BUFFER]; LXI D,BUFFER DAD D XCHG LHLD ZZIP LXI B,NEXTP DAD B MOV M,E INX H MOV M,D LHLD ZZUNIT ; fcb(unit,name); PUSH H LHLD ZZFILE PUSH H CALL FCB POP H POP H LHLD ZZUNIT ; cpmdisk(*unit); MOV L,M MVI H,0 PUSH H CALL CPMDISK POP H LHLD ZZMODE ;if(*mode=='R'||*mode=='A'){ MOV A,M ; ANI 5FH ;# CONVERT TO UPPERCASE CPI 'R' ;# MODE = R ? JNZ FOPIF1 ; FOPIF0: MVI C,OPEN ; if(cpm(OPEN,unit)<0){ LHLD ZZUNIT XCHG CALL CBDOS ; (mod tocbdos (fas)) ORA A JP FOPIF2 LHLD ZZUNIT ; freeio(unit); PUSH H CALL FREEIO POP H LXI H,NULL ; return(NULL); RET ; } FOPIF2: LHLD ZZIP ; ZZIP[UNUSED] = 0; LXI D,UNUSED DAD D LXI D,0 MOV M,E INX H MOV M,D ; } JMP FOPIFX FOPIF1: ; else if(*mode=='W'){ LHLD ZZMODE MOV A,M ANI 5FH CPI 'W' ;# WRITE MODE ? JZ FOPIFA ;# YES - GO DO IT CPI 'A' ;# APPEND MODE ? JNZ FOPIF5 ;# NO - BACK TO CALLER OF FOPEN ; ;# NO MODES LEFT TO TRY ; MVI C,OPEN ;# FIRST LET'S SEE IF IT'S THERE LHLD ZZUNIT XCHG CALL CBDOS ORA A JP FOPIF3 ;# YES - SET IT UP FOR USE ; ;# NO - LET'S MAKE ONE LHLD ZZMODE ;# SET MODE TO 'W' ON NEW FILE MVI M,'W' ;# TO AVOID WASTING TIME AND CODE ;# SEARCHING AN EMPTY FILE ; FOPIFA: MVI C,DELETE ; cpm(DELETE,unit); LHLD ZZUNIT XCHG CALL CBDOS ; (mod to cbdos(fas)) MVI C,CREATE ; if(cpm(CREATE,unit)<0){ LHLD ZZUNIT XCHG CALL CBDOS ; (mod to cbdos(fas)) ORA A JP FOPIF3 LHLD ZZUNIT ; freeio(unit); PUSH H CALL FREEIO POP H LXI H,NULL ; return(NULL); RET ; } FOPIF3: LHLD ZZIP ; ZZIP[UNUSED] = BUFSIZ; LXI D,UNUSED DAD D LXI D,BUFSIZ MOV M,E INX H MOV M,D LHLD ZZUNIT ; unit[FLAG] = WRITE_FL; LXI D,FLAG DAD D MVI A,WRTFLG ORA M MOV M,A JMP FOPIF4 ; } FOPIF5: LHLD ZZUNIT ; else{ freeio(unit); PUSH H CALL FREEIO POP H LXI H,NULL ; return(NULL); RET ; ; } FOPIF4: ; LHLD ZZMODE ;# MOV A,M ;# GET MODE ANI 5FH CPI 'A' ;# APPEND MODE ? JNZ FOPIFX ;# NO - RETURN NORMALLY ; AMSCRD: ; LDA CUREXT ;# SAVE EXTENT AND RECORD NUMBERS STA OLDEXT ;# TWO DEEP LDA CURREC STA OLDREC LHLD ZZUNIT LXI D,12 DAD D MOV A,M ;# GET CURRENT EXTENT # STA CUREXT LXI D,20 DAD D MOV A,M ;# GET CURRENT RECORD # STA CURREC ; LHLD ZZUNIT ;# YES - LET'S READ TO THE END XCHG ;# DE --> FCB MVI C,READ CALL CBDOS ;# READ A SECTOR ORA A JZ AMSCRD ;# READ TO PHYSICAL END OF FILE ; LHLD ZZUNIT LXI D,12 DAD D LDA OLDEXT MOV M,A ;# RESTORE LAST EXTENT # LXI D,20 DAD D LDA OLDREC MOV M,A ;# RESTORE LAST RECORD # ; LXI H,ZZBUF SHLD ZZTEMP ;# SAVE THE BUFF. WE'RE READING FROM AMCHRD: LHLD ZZTEMP ;# HL --> TEMPORARY BUFFER MOV A,M ; CPI 0AH ;# LINE FEED CHECK JNZ NOTLF INX H ;# INCREMENT POINTER SHLD ZZTEMP ;# AND GO ON TO NEXT CHARACTER JMP AMCHRD ; NOTLF: CPI 1AH ;# END OF FILE MARKER ? JZ FOPIFX ;# YES - EXIT GRACEFULLY MOV C,A MVI B,0 ;# BC CONTAINS THE CHARACTER INX H SHLD ZZTEMP ;# SAVE UPDATED POINTER MOV A,L ORA A ;# END OF BUFFER ? JZ FOPIFX ;# YES - EXIT JUST AS GRACEFUL LHLD ZZUNIT PUSH B PUSH H CALL PUTC ;# PUTC(CHAR,ZZUNIT) POP B POP B JMP AMCHRD ;# CONTINUE SCANNING ; FOPIFX: LHLD ZZUNIT ; return(unit); RET ; FCLOSE:: POP B POP H SHLD ZZUNIT PUSH H PUSH B MOV A,H ; if (unit<256) ORA A ; /* assume stdin, stdout, etc. */ MVI L,0 RZ ; return NULL; LXI H,1 ; t = 1; SHLD ZZT LHLD ZZUNIT ; if(unit[FLAG] & WRITE_FL){ LXI D,FLAG DAD D MOV A,M ANI WRTFLG JZ FCLIF1 LXI H,CTRLZ ; putc(CTRL_Z,unit); PUSH H LHLD ZZUNIT PUSH H CALL PUTC POP H POP H LHLD ZZUNIT ; ZZIP = unit + FCBSIZE; LXI D,FCBSIZE DAD D SHLD ZZIP LHLD ZZIP ; cp = ZZIP[NEXTP]; LXI D,NEXTP DAD D MOV E,M INX H MOV D,M XCHG SHLD ZZCHP LHLD ZZIP ; ZZDP = &ZZIP[BUFFER]+BUFSIZ; LXI D,BUFFER+BUFSIZ DAD D SHLD ZZDP FCLWH1: ; while(cp'a'-'A') /* lower case? */ JC FCBIF2 SUI 61H-41H ; A -= 'a'-'A' JMP FCBIF2 ; } FCBIF1: LDA ZZDFLT ; else A = default_drive; FCBIF2: STAX B ; *fp++ = A; INX B MVI H,' ' ; fp = fcbfill(fp,name,' ',8); MVI L,8 CALL FCBFILL MVI L,3 ; fp = fcbfill(fp,name,' ',3); CALL FCBFILL MVI H,0 ; fp = fcbpad(fp,0,4); MVI L,4 CALL FCBPAD LXI H,16 ; fp[16] = 0; DAD B MVI M,0 RET ; return; ; ; fcbfill(dest,name,pad,size) ; B D H L ; FCBFILL:: MOV A,L ; while(L>0 && (A= *D)~='.' && A~=0){ ORA A JZ FILL2 LDAX D CPI '.' JZ FILL2 CPI 0 JZ FILL2 CPI 61H ; if(A>='a' && A<='z') JC FILL1 CPI 7AH+1 ; 'z' 9 Jun 80 rj JNC FILL1 SUI 61H-41H ; A = A - 'a' + 'A'; FILL1: STAX B ; *B++ = A; INX B INX D ; D++; DCR L ; L--; JMP FCBFILL ; } FILL2: LDAX D ; while(*D~='.' && *D~=0) CPI '.' JZ FILL3 CPI 0 JZ FILL3 INX D ; D++; JMP FILL2 FILL3: CPI '.' ; if(*D=='.') JNZ FILL4 INX D ; D++; FILL4: ; fall into... ; ; fcbpad(dest,pad,size) ; B H L ; FCBPAD:: MOV A,L ; while(L>0){ ORA A JZ PAD2 MOV A,H ; *B++ = H; STAX B INX B DCR L ; L--; JMP FCBPAD ; } PAD2: RET ; return; ; ; END #define NOCCARGC /* ** Yes, that is correct. Although these functions use an ** argument count, they do not call functions which need one. */ #include stdio.h /* ** fprintf(fd, ctlstring, arg, arg, ...) - Formatted print. ** Operates as described by Kernighan & Ritchie. ** b, c, d, o, s, u, and x specifications are supported. ** Note: b (binary) is a non-standard extension. */ fprintf(argc) int argc; { int *nxtarg; nxtarg = CCARGC() + &argc; return(Uprint(*(--nxtarg), --nxtarg)); } /* ** printf(ctlstring, arg, arg, ...) - Formatted print. ** Operates as described by Kernighan & Ritchie. ** b, c, d, o, s, u, and x specifications are supported. ** Note: b (binary) is a non-standard extension. */ printf(argc) int argc; { return(Uprint(stdout, CCARGC() + &argc - 1)); } /* ** Uprint(fd, ctlstring, arg, arg, ...) ** Called by fprintf() and printf(). */ Uprint(fd, nxtarg) int fd, *nxtarg; { int arg, left, pad, cc, len, maxchr, width; char *ctl, *sptr, str[17]; cc = 0; ctl = *nxtarg--; while(*ctl) { if(*ctl!='%') {fputc(*ctl++, fd); ++cc; continue;} else ++ctl; if(*ctl=='%') {fputc(*ctl++, fd); ++cc; continue;} if(*ctl=='-') {left = 1; ++ctl;} else left = 0; if(*ctl=='0') pad = '0'; else pad = ' '; if(isdigit(*ctl)) { width = atoi(ctl++); while(isdigit(*ctl)) ++ctl; } else width = 0; if(*ctl=='.') { maxchr = atoi(++ctl); while(isdigit(*ctl)) ++ctl; } else maxchr = 0; arg = *nxtarg--; sptr = str; switch(*ctl++) { case 'c': str[0] = arg; str[1] = NULL; break; case 's': sptr = arg; break; case 'd': itoa(arg,str); break; case 'b': itoab(arg,str,2); break; case 'o': itoab(arg,str,8); break; case 'u': itoab(arg,str,10); break; case 'x': itoab(arg,str,16); break; default: return (cc); } len = strlen(sptr); if(maxchr && maxchrlen) width = width - len; else width = 0; if(!left) while(width--) {fputc(pad,fd); ++cc;} while(len--) {fputc(*sptr++,fd); ++cc; } if(left) while(width--) {fputc(pad,fd); ++cc;} } return(cc); }  ; ; putc(c,unit) ; ; CBDOS EQU 5 ;/* bdos entry point */ CPMARG EQU 128 ;/* CP/M command line */ MAXARG EQU 32 ;/* Maximum number of input args */ STDIN EQU 0 STDOUT EQU 1 STDERR EQU 2 STDLST EQU 4 CTRLZ EQU 26 ;control z NULL EQU 0 ;pointer to nothing FCBSIZE EQU 36 ;size, in bytes, of an FCB NEXTP EQU 0 ;offset to next-character pointer in I/O structure UNUSED EQU 2 ;offset to unused-positions-count in I/O structure BUFFER EQU 6 ;offset to disk sector buffer in I/O structure UNGOT EQU 5 ;offset to char ungotten by ungetc() FLAG EQU 33 ;file-type flag byte (in unused part of FCB) FREEFLG EQU 128 ;This I/O structure is available for the taking EOFFLG EQU 2 ;The end of this file has been hit WRTFLG EQU 1 ;This file open for writing BUFSIZ EQU 1024 ;how long the sector buffer is NBUFS EQU 8 ;number of I/O buffers TBUFF EQU 128 ;default cpm buffer LF EQU 10 EOL EQU 13 ; ; CP/M BDOS CALLS ; CLOSE EQU 16 ;close a file CPMSTR EQU 9 ;print '$' delimited string on console CREATE EQU 22 ;make a file DMA EQU 26 ;set DMA (I/O address) DELETE EQU 19 ;delete a file GETCH EQU 1 ;read character from console GETSTR EQU 10 ;read string from console LSTOUT EQU 5 ;write character to list device OPEN EQU 15 ;open a file PUTCH EQU 2 ;write character to console QUERY EQU 25 ;get logged-in drive id READ EQU 20 ;read a sector SELECT EQU 14 ;log-in a drive WRITE EQU 21 ;write a sector ; ; File i/o storage varibles found in ulink() ; EXTRN ZZUNIT EXTRN ZZIP EXTRN ZZCHP EXTRN ZZDP EXTRN ZZFILE EXTRN ZZMODE EXTRN ZZCH EXTRN ZZT EXTRN ZZFN EXTRN ZZNUBU EXTRN ZZMXSC ; ; Characteristics variable storage found in ulink() ; EXTRN ZZSVCH EXTRN ZZDFLT EXTRN ZZSTAK EXTRN ZZMEM ; EXTRN PUTCHAR EXTRN PUTLIST EXTRN CPMIO ; FPUTC:: PUTC:: POP B ;rtn addr POP D ;unit POP H ;c PUSH H PUSH D PUSH B MOV A,D ORA A ; if(unit < 256) { JNZ PUTC4 ; /* assume stdout, stderr */ MOV A,E ; /* or stdlist. */ CPI STDOUT ; if(unit == stdout) { JNZ PUTC1 PUSH H CALL PUTCHAR ; putchar(c); POP H RET ; return;} PUTC1: CPI STDERR ; elseif(unit == stderr) { JNZ PUTC2 CALL PUTCHAR ; putchar(c); RET ; return;} PUTC2: CPI STDLST ; elseif(unit == stdlist) { JNZ PUTC3 PUSH H CALL PUTLIST ; putlist(c); POP H RET ; return;} PUTC3: JMP PTCER1 ; else goto putcerr; } PUTC4: PUSH H ; if(cput(c,unit)<0) PUSH D ; goto putcerr; CALL CPUT POP D MOV A,H ORA A JM PUTCERR MOV A,L ; if(c=='\r') CPI EOL JNZ PUTCRET LXI H,LF ; cput('\n',unit); PUSH H PUSH D CALL CPUT POP D POP D MOV A,H ORA A JM PUTCERR PUTCRET: POP H ; return(c); RET PUTCERR: ;putcerr: POP B ; return(-1); PTCER1: LXI H,-1 RET ; ; cput(c,unit) ; CPUT:: POP B POP D POP H PUSH H PUSH D PUSH B SHLD ZZCH XCHG SHLD ZZUNIT LXI D,FCBSIZE ; ip = unit + FCBSIZE; DAD D SHLD ZZIP LXI D,NEXTP ; cp = ip[NEXTP]; DAD D MOV E,M INX H MOV D,M XCHG SHLD ZZCHP LHLD ZZIP ; if(ip[UNUSED]==0){ LXI D,UNUSED DAD D MOV A,M INX H ORA M JNZ PTCIF1 LXI H,WRITE ; if(cpmio(WRITE,unit)~=0) PUSH H LHLD ZZUNIT PUSH H CALL CPMIO POP D POP D MOV A,H ORA L JZ PTCIF2 LXI H,-1 ; return(-1); RET PTCIF2: LHLD ZZIP ; else { ip[UNUSED] = BUFSIZ; LXI D,UNUSED DAD D LXI D,BUFSIZ MOV M,E INX H MOV M,D LHLD ZZIP ; cp = &ip[BUFFER]; LXI D,BUFFER DAD D SHLD ZZCHP ; } ; } PTCIF1: LHLD ZZIP LXI D,UNUSED ; ip[UNUSED]--; DAD D MOV E,M INX H MOV D,M DCX D MOV M,D DCX H MOV M,E LHLD ZZCHP ; ip[NEXTP] = cp+1; INX H XCHG LHLD ZZIP LXI B,NEXTP DAD B MOV M,E INX H MOV M,D LDA ZZCH ; return((*cp = c) & 0377); LHLD ZZCHP MOV M,A MVI H,0 MOV L,A RET END  ; ; fputs(cp,unit) ; ; CBDOS EQU 5 ;/* bdos entry point */ CPMARG EQU 128 ;/* CP/M command line */ MAXARG EQU 32 ;/* Maximum number of input args */ STDIN EQU 0 STDOUT EQU 1 STDERR EQU 2 STDLST EQU 4 CTRLZ EQU 26 ;control z NULL EQU 0 ;pointer to nothing FCBSIZE EQU 36 ;size, in bytes, of an FCB NEXTP EQU 0 ;offset to next-character pointer in I/O structure UNUSED EQU 2 ;offset to unused-positions-count in I/O structure BUFFER EQU 6 ;offset to disk sector buffer in I/O structure UNGOT EQU 5 ;offset to char ungotten by ungetc() FLAG EQU 33 ;file-type flag byte (in unused part of FCB) FREEFLG EQU 128 ;This I/O structure is available for the taking EOFFLG EQU 2 ;The end of this file has been hit WRTFLG EQU 1 ;This file open for writing BUFSIZ EQU 1024 ;how long the sector buffer is NBUFS EQU 8 ;number of I/O buffers TBUFF EQU 128 ;default cpm buffer LF EQU 10 EOL EQU 13 ; ; CP/M BDOS CALLS ; CLOSE EQU 16 ;close a file CPMSTR EQU 9 ;print '$' delimited string on console CREATE EQU 22 ;make a file DMA EQU 26 ;set DMA (I/O address) DELETE EQU 19 ;delete a file GETCH EQU 1 ;read character from console GETSTR EQU 10 ;read string from console LSTOUT EQU 5 ;write character to list device OPEN EQU 15 ;open a file PUTCH EQU 2 ;write character to console QUERY EQU 25 ;get logged-in drive id READ EQU 20 ;read a sector SELECT EQU 14 ;log-in a drive WRITE EQU 21 ;write a sector ; ; File i/o storage varibles found in ulink() ; EXTRN ZZUNIT EXTRN ZZIP EXTRN ZZCHP EXTRN ZZDP EXTRN ZZFILE EXTRN ZZMODE EXTRN ZZCH EXTRN ZZT EXTRN ZZFN EXTRN ZZNUBU EXTRN ZZMXSC ; ; Characteristics variable storage found in ulink() ; EXTRN ZZSVCH EXTRN ZZDFLT EXTRN ZZSTAK EXTRN ZZMEM ; EXTRN PUTC ; FPUTS:: POP B POP D ; unit POP H ; cp PUSH H PUSH D PUSH B FPUTS1: MOV A,M ; while((c=*cp++) <> NULL) { INX H ORA A JZ FPUTS3 PUSH H MOV C,A MVI B,0 PUSH B PUSH D CALL PUTC ; if(putc(c,unit)==EOF) POP D POP B MOV A,H ORA A JZ FPUTS2 POP B RET ; return(EOF); FPUTS2: POP H JMP FPUTS1 ; } FPUTS3: LXI H,0 RET ; return(NULL); END FPUTS /* ** fread.c by F.A.Scacchitti 9/3/84 */ fread(buf, sz, n, fd) char *buf; int sz, n, fd; { return(read(fd, buf, n*sz)); }  /* ** frebufc.c by fas 8/30/84 */ #include frebuf(buffer) int buffer; { freeio(buffer-42); return(NULL); } #define NOCCARGC /* no argument count passing */ extern char *zzmem; /* ** free(ptr) - Free previously allocated memory block. ** Memory must be freed in the reverse order from which ** it was allocated. ** ptr = Value returned by calloc() or malloc(). ** Returns ptr if successful or NULL otherwise. */ free(ptr) char *ptr; { return (zzmem = ptr); } #asm cfree equ free entry cfree #endasm ; ; freeio(unit) by F.A.Scacchitti 9/12/84 ; ; mark a buffer as free. ; ; ; NBUFS EQU 8 FCBSIZE EQU 36 ;size, in bytes, of an FCB BUFFER EQU 6 ;offset to disk sector buffer in I/O structure FLAG EQU 33 ;file-type flag byte (in unused part of FCB) FREEFLG EQU 128 ;This I/O structure is available for the taking BUFSIZ EQU 1024 ;how long the sector buffer is NULL EQU 0 ; EXTRN IOBUFS ; ; FREEIO:: ;Mod 6 May 80 rj POP B ;save rtn addr POP H ;get buffer addr PUSH H ;put the stack back together PUSH B LXI D,FLAG ;find flag byte DAD D MVI M,FREEFLG ;mark buffer as 'free' LXI H,NULL ;return something RET END #define NOCCARGC /* no argument count passing */ /* ** Yes, that is correct. Although these functions use an ** argument count, they do not call functions which need one. */ #include stdio.h /* ** fscanf(fd, ctlstring, arg, arg, ...) - Formatted read. ** Operates as described by Kernighan & Ritchie. ** b, c, d, o, s, u, and x specifications are supported. ** Note: b (binary) is a non-standard extension. */ fscanf(argc) int argc; { int *nxtarg; nxtarg = CCARGC() + &argc; return (Uscan(*(--nxtarg), --nxtarg)); } /* ** scanf(ctlstring, arg, arg, ...) - Formatted read. ** Operates as described by Kernighan & Ritchie. ** b, c, d, o, s, u, and x specifications are supported. ** Note: b (binary) is a non-standard extension. */ scanf(argc) int argc; { return (Uscan(stdin, CCARGC() + &argc - 1)); } /* ** Uscan(fd, ctlstring, arg, arg, ...) - Formatted read. ** Called by fscanf() and scanf(). */ Uscan(fd,nxtarg) int fd, *nxtarg; { char *carg, *ctl, *unsigned; int *narg, wast, ac, width, ch, cnv, base, ovfl, sign; ac = 0; ctl = *nxtarg--; while(*ctl) { if(isspace(*ctl)) {++ctl; continue;} if(*ctl++ != '%') continue; if(*ctl == '*') {narg = carg = &wast; ++ctl;} else narg = carg = *nxtarg--; ctl += utoi(ctl, &width); if(!width) width = 32767; if(!(cnv = *ctl++)) break; while(isspace(ch = fgetc(fd))) ; if(ch == EOF) {if(ac) break; else return(EOF);} ungetc(ch,fd); switch(cnv) { case 'c': *carg = fgetc(fd); break; case 's': while(width--) { if((*carg = fgetc(fd)) == EOF) break; if(isspace(*carg)) break; if(carg != &wast) ++carg; } *carg = 0; break; default: switch(cnv) { case 'b': base = 2; sign = 1; ovfl = 32767; break; case 'd': base = 10; sign = 0; ovfl = 3276; break; case 'o': base = 8; sign = 1; ovfl = 8191; break; case 'u': base = 10; sign = 1; ovfl = 6553; break; case 'x': base = 16; sign = 1; ovfl = 4095; break; default: return (ac); } *narg = unsigned = 0; while(width-- && !isspace(ch=fgetc(fd)) && ch!=EOF) { if(!sign) if(ch == '-') {sign = -1; continue;} else sign = 1; if(ch < '0') return (ac); if(ch >= 'a') ch -= 87; else if(ch >= 'A') ch -= 55; else ch -= '0'; if(ch >= base || unsigned > ovfl) return (ac); unsigned = unsigned * base + ch; } *narg = sign * unsigned; } ++ac; } return (ac); } /* ** fwrite.c by F.A.Scacchitti 9/3/84 */ fwrite(buf, sz, n, fd) char *buf; int sz, n, fd; { return(write(fd, buf, n*sz)); } #define NOCCARGC /* no argument count passing */ /* * getchar() Normal console input via BDOS(1) */ #include getchar(){ char c; c = bdos(1,0); if(c == 26) return(-1); else return(c); } /* ** getchx() Direct console input via BDOS(6) */ #include getchx() { char c; while(!(c = bdos(6,255))); return(c); }  ; ; gets(buff) ; ; CBDOS EQU 5 ;/* bdos entry point */ CPMARG EQU 128 ;/* CP/M command line */ MAXARG EQU 32 ;/* Maximum number of input args */ STDIN EQU 0 STDOUT EQU 1 STDERR EQU 2 STDLST EQU 4 CTRLZ EQU 26 ;control z NULL EQU 0 ;pointer to nothing FCBSIZE EQU 36 ;size, in bytes, of an FCB NEXTP EQU 0 ;offset to next-character pointer in I/O structure UNUSED EQU 2 ;offset to unused-positions-count in I/O structure BUFFER EQU 6 ;offset to disk sector buffer in I/O structure UNGOT EQU 5 ;offset to char ungotten by ungetc() FLAG EQU 33 ;file-type flag byte (in unused part of FCB) FREEFLG EQU 128 ;This I/O structure is available for the taking EOFFLG EQU 2 ;The end of this file has been hit WRTFLG EQU 1 ;This file open for writing BUFSIZ EQU 1024 ;how long the sector buffer is NBUFS EQU 8 ;number of I/O buffers TBUFF EQU 128 ;default cpm buffer LF EQU 10 EOL EQU 13 ; ; CP/M BDOS CALLS ; CLOSE EQU 16 ;close a file CPMSTR EQU 9 ;print '$' delimited string on console CREATE EQU 22 ;make a file DMA EQU 26 ;set DMA (I/O address) DELETE EQU 19 ;delete a file GETCH EQU 1 ;read character from console GETSTR EQU 10 ;read string from console LSTOUT EQU 5 ;write character to list device OPEN EQU 15 ;open a file PUTCH EQU 2 ;write character to console QUERY EQU 25 ;get logged-in drive id READ EQU 20 ;read a sector SELECT EQU 14 ;log-in a drive WRITE EQU 21 ;write a sector ; ; File i/o storage varibles found in ulink() ; EXTRN ZZUNIT EXTRN ZZIP EXTRN ZZCHP EXTRN ZZDP EXTRN ZZFILE EXTRN ZZMODE EXTRN ZZCH EXTRN ZZT EXTRN ZZFN EXTRN ZZNUBU EXTRN ZZMXSC ; ; Characteristics variable storage found in ulink() ; EXTRN ZZSVCH EXTRN ZZDFLT EXTRN ZZSTAK EXTRN ZZMEM ; EXTRN GETC ; GETS:: POP B POP H PUSH H PUSH B SHLD ZZCHP DCX H ; save = buff[-1]; save2 = buff[-2]; MOV D,M ; buff[-1] = 0; buff[-2] = 79; MVI M,0 DCX H MOV E,M MVI M,79 ;6 May 80 rj PUSH H PUSH D XCHG ; cpm(GETSTR,buff-2); MVI C,GETSTR CALL CBDOS ; (mod to cbdos(fas)) LHLD ZZCHP ; buff[buff[-1]] = 0; (9 Jun 80. Was cp) DCX H MOV E,M INX H MVI D,0 DAD D MVI M,0 POP D ; buff[-1] = save; buff[-2] = save2; POP H MOV M,E INX H MOV M,D INX H MVI C,PUTCH ; putchar('\n'); MVI E,LF CALL CBDOS ; (mod to cbdos(fas)) LHLD ZZCHP ; return(buff); RET ; } END GETS ; ; grabio() by F.A.Scacchitti 9/18/84 ; ; find an input buffer, and return its address. ; if there isn't one, return a NULL. ; ; NBUFS EQU 8 FCBSIZE EQU 36 ;size, in bytes, of an FCB BUFFER EQU 6 ;offset to disk sector buffer in I/O structure FLAG EQU 33 ;file-type flag byte (in unused part of FCB) FREEFLG EQU 128 ;This I/O structure is available for the taking BUFSIZ EQU 1024 ;how long the sector buffer is NULL EQU 0 TBUFSZ EQU 128 ; Default buffer size ; EXTRN ZZBUF ; GRABIO:: ;6 May 80 rj MVI B,NBUFS LXI H,ZZBUF+TBUFSZ+FLAG LXI D,FCBSIZE+BUFFER+BUFSIZ MVI A,FREEFLG GRAB2: CMP M ;flag byte == freeflg? JZ GRAB3 ;if so, found a free buffer DAD D ;on to next buffer DCR B JNZ GRAB2 ;if there is one... LXI H,NULL ;there ain't RET ;give up ; GRAB3: MVI M,0 ;mark buffer as taken LXI D,-FLAG ;back up to buffer start DAD D RET ;and hand it back ; END  /* ** grabufc.c by fas 8/30/84 */ #include grabuf() { int buf; if((buf = grabio) != NULL) return(buf+42); return(NULL); }  ; inp(port#) ; Added 2/84 (fas) INP:: INX SP ; Skip over return address INX SP POP B ; Load port # into C DB 0EDH, 068H ; Do instruction PUSH B ; Restore stack DCX SP DCX SP MOV A,L ; Data was returned in L RLC ; Sign extend HL SBB A ; MOV H,A ; That's it RET END /* ** return 'true' if c is alphanumeric */ isalnum(c) int c; { return ((c<='z' && c>='a') || (c<='Z' && c>='A') || (c<='9' && c>='0')); } /* ** return 'true' if c is alphabetic */ isalpha(c) int c; { return ((c<='z' && c>='a') || (c<='Z' && c>='A')); } /* ** return 'true' if c is an ASCII character (0-127) */ isascii(c) char *c; { /* c is a simulated unsigned integer */ return (c <= 127); } /* ** Return "true" if fd is a device, else "false" */ #include isatty(fd) int fd; { if(fd >255) return(FALSE); else return(TRUE); } /* ** return 'true' if c is a control character ** (0-31 or 127) */ iscntrl(c) char *c; { /* c is a simulated unsigned integer */ return ((c <= 31) || (c == 127)); } /* ** return 'true' if c is a decimal digit */ isdigit(c) int c; { return (c<='9' && c>='0'); } /* ** return 'true' if c is a graphic character ** (33-126) */ isgraph(c) int c; { return (c>=33 && c<=126); } /* ** return 'true' if c is lower-case alphabetic */ islower(c) int c; { return (c<='z' && c>='a'); } /* ** return 'true' if c is a printable character ** (32-126) */ isprint(c) int c; { return (c>=32 && c<=126); } #define NOCCARGC /* no argument count passing */ /* ** return 'true' if c is a punctuation character ** (all but control and alphanumeric) */ ispunct(c) int c; { return (!isalnum(c) && !iscntrl(c)); } /* ** return 'true' if c is a white-space character */ isspace(c) int c; { /* first check gives quick exit in most cases */ return(c<=' ' && (c==' ' || (c<=13 && c>=9))); } /* ** return 'true' if c is upper-case alphabetic */ isupper(c) int c; { return (c<='Z' && c>='A'); } /* ** return 'true' if c is a hexadecimal digit ** (0-9, A-F, or a-f) */ isxdigit(c) int c; { return ((c<='f' && c>='a') || (c<='F' && c>='A') || (c<='9' && c>='0')); } #define NOCCARGC /* no argument count passing */ /* ** itoa(n,s) - Convert n to characters in s */ itoa(n, s) char *s; int n; { int sign; char *ptr; ptr = s; if ((sign = n) < 0) /* record sign */ n = -n; /* make n positive */ do { /* generate digits in reverse order */ *ptr++ = n % 10 + '0'; /* get next digit */ } while ((n = n / 10) > 0); /* delete it */ if (sign < 0) *ptr++ = '-'; *ptr = '\0'; reverse(s); } #define NOCCARGC /* no argument count passing */ /* ** itoab(n,s,b) - Convert "unsigned" n to characters in s using base b. ** NOTE: This is a non-standard function. */ itoab(n, s, b) int n; char *s; int b; { char *ptr; int lowbit; ptr = s; b >>= 1; do { lowbit = n & 1; n = (n >> 1) & 32767; *ptr = ((n % b) << 1) + lowbit; if(*ptr < 10) *ptr += '0'; else *ptr += 55; ++ptr; } while(n /= b); *ptr = 0; reverse (s); } vUW.C [04/07/91]% @h(T*N$F4 y Ri7 Dr0A&(\Afi: "^2H<&S  f -! SoȀr 4& &S@t7IT-;L3 0B9G9u2EG%\hgB=!H2Ih  G#-eZD(bI":d\Ag0v-Gb޳xӛc!t`HH_M`oW+i皹? Z$C3m`@HizPAt3 @6S 38Nh0f:P8<#P p341k|I)E H<'AD AM@P*p̌*S-"XRHp& Fo@1" 6)ҼJLS$ /lSD;>OεAPD@1C*ڊ ,Bt.:K54ScrLT52SYAcfڶ(S MCIe2 NHl6 HbJ@qLa13aGE)Hi0L%C) M :͑3ȸ@G4֡i7[Dl2$n:&t Si*J*r%K;bL\R4b1U/l6o6Cyt4ho""FY> Nu6UQ%5F+hw84x4s@0h׭Csd۶@ܪ@dN12SҎJ2M; #:H7 h҂iN?,"clu_~eƳ6L ~gl)40 d41l巸PY?Dp@k~0%[ERj-2( Zt'JhqZ>U 45qa.$̍Cz{ŕÕ