1SD68K DQCSD REL&SD SQ <9YENDJOB S uCRLF S xDCOUT S |SORT S )MD5DC S /lOPTSCN S cOPTSET S MAKEFCB S ~CAPS S HLOSD SUBXvtSD68K.DOCo   !o"$#%'&()+*,-/._0132457689:;<>=@?ABDCEF HGJIK MLNOrPQRUSWXVTYS\Z[]_`^cabd4Qe hjgfiklnmXB;,Du#1_lEQHLxSn|FbkO>D[_Do(u!XV\%Jͬ3m4GpV'?mn)[V .rKۜ^ߖ`(7:Lx5ۜԽ=RSpWLkIjZsp+7Df."nH[ySk[ QnŘ[oJVԂ{n+7mQҐm}skϢNr<<9 N1 vCק"}!m-Oܾ, b|DxfS wEܷm/eųoPu-QnLsu+: ]:z(PP׻0-K. i˼)zr`_[y\{(^ynC2*ZoJSp^T;TzԎI/j` ~ R,"z~(Gl_o%J> ෨O># Zzzn]Z*['vmᆴ'Eڲ_U(7|[y\E3zzn45[a{z]搖[0&mCw!,!ƎH#]G7&}H|EnrC3I_nrC}[Ԑ]K~N>7zow-QnK~{T ҮnT()57H׽t>#ѥv۝9FԚ F>#6ug?}i:h&GJl(H0v Hww>DWa% }_;X>(R2&ouQ Ǥ펞4IH,]N)hDY$n9T1egT_?kP|F`hI/S7S՟g5xHkfn|FZ+ikpg䓏uӟ3_ ~;I`~X4W~{z !=`>#̟U^t?1nw>TU4}zO># 5o#5U_wlHkH:CǤlLxu;t5;Җ=R=~-/UE߯ŋ3ja [3U_wlHkH:CǤlLxu;t =}T_Q?ګ:/FҗHzUxoi!,!PjՇ7Ge8ܠS3ZG1emgg$;zGI+Ĝ'Z8UE߯>1i>{>^suk'PT_P3)-J׫<|F@qR}'Ls[W%x>#]v.}W3?g'~}?4Ot*QNHj,OO>i+r@w>]搖[0&mCw!,!ƎH#]G7&}H|EnrC3I_nrC}[Ԑ]K~N>`l0By By #  "< pNBpNBH3#~ /"<$<B(<NJgd?"<pNB` "<pNB gFX r @"y J9f( fQRI# Ry NzJy g*"<3 N | 2y aN"<p NBN9 g@H | p Q"<pNB"<pNB nD"< pNBL9gHSApNB"< pNB9 H39 H3J9g 29pNB3 99 g RHy By By By By ( B69CFCCHy BC( ygCSB`y p $H&HfQ JSI`Ry 49 y &| J6666RK 9g 29 HN\&@ 9g:& W(|gRRgSRgAR   $"9# J"<Ha*L49 RB3 y f By aSI fJy gaj9f29RASA?p.,9 NB"9 9 g "9 # <nAN\0A@p "<NB" < N\ H I <T29 HN\ <^29 N\"<6a89 g*9 g"<pNBJfl"<pNB n\Nu9 fp NBNu"A $ga`NuH y# gLNu# "<pNBJg"<p NB`* | p Q`H"<2axLNuB@NB/r Nr N"NuHpNBLNuH"A$Q<) Fo@܊*F* &J,iNo*J,K6)SCQmmLNuH 0ffL NuH`@"@ZItH HA|0HAQt 0f QZ@LNu// @ g g -gz $gr *g gB Aml Znf"g SN @Jf"<`X"g N @Jf"<`>"g N @Jfz"<`" "NZ @Jg`^S"<p NBB"  _NuH@ @ Am" Zn"AJfB`gT`R R` LNuH$A"A @pBYQ"A" #| #| B (:f(N@T  nRHRIr ?Q`RpN 0m Q` *g ?g .g  nV`X?Q`"J pN 0mQ  n$`& ?g *f ?Q` g  gB`" SH LNu am zn_Nu????????????DIRLIST LIS No files $ Error writing output file. $xxxxxxxx.xxxnnnnn ars $ $ Drive x, user nn, containsnnnnnk in nnnnn files withnnnnnk free. $ HFKS Illegal option [x] $ Bad file spec. $ Illegal input re-direct $ Illegal output re-diredt $endjobcrlfcoutsortcmpa12Hmd5dc\optscnoptsetZmakefcbcapsvSD.SS  !"#$&%')(+*,.-/02143o56789:;<=>?A@BCDFEGIHJKMLNOQPR%F!n݊qv5/R/H7n]3Vo]R/i{KA2S4V$ mub~)9zp#x𚑾NRlw/R:ۓ8b3tz_!RC {$[/R/z&:d+։8v?6cn]3=R vITj8Ҍ_ /zlƪш.J ;_)nwZZX[{9dFYXqH3ص~)J~)H[ݑfj+n--bp[4KyChDhD.r*5KyxKϸD-j#µSIo:hKAjNpRү$}KAڍRmgn~1ZZ pzKAڍV$jiU3iܴKy.A-uUf{([jdT1/i7"Ա:cn bis/RvcVgZ 7ĭzRvcB?qkE4T[ź۝Yi*pق_ mGŮYDP'瘈c4^J*# /}P]۾Ի}՛{T׶ovrյ}P]۾bK͵ lΌ6rj:mw@ %9$ݮ>Ό6;9rC%9.>ΌzɝwyPvjЫ:r%"X3>:a0LL% }wn'bʨ~>ΌzYk%tvvL~y_ tv‘Nܐ5/h./g> |J}^{_/:;! Oo8]?mۙWs|}'b sr@k]vVyކ1>6wr@k%9qv8]},>꜄6.93r@ kke:U2{lgF(XZ>Ό6ߖeQz(ת}xaq@*Z8LJj̩#%JScy^tGJTq414{_wvfԃSGԜ>3#%KÑf!*#lgF=:r%5XȕܴQ˚3 5ǷQ%莰~yO꛽_ޟj3xo8@k]vcьI]gwmb;ҀKKX\ͪx3 R&g>Όv#ǷtCP}mOdۙv#k>އ^ԻR v8Lۉv vfgb;QbD`T`;a9^>&/K҉8qo~y87eq_q[]8z}q3[3ކ;vr#B-v_ۙ1P[58u}mwr|dۙvlgFx5y:r"J\j8g}L+(]>Ό6;9rwr@i͎uЅ#u}lgFwy9vf9%XM64{}\l!ԃs|^wb%c/&Ѕ#ۙ~''N}x9^ PvbgGJ>z3cSWqdoҏolgF=߇a,%i&$Vne}CP˙3?8.@ eͮ~|`;3+`;3s|(Xj̎87{lgF=]~N%tv·}*}C`;3QۙQe_K'>!}(ힽpކ(1դb0qvtSvۙJTr&>N x-P-eͮ\My7> [(H3hD`;3ZəĵҮp^B:'pUB?ʙoXm1ZZՌzuar߇Jᮝ~y pMJ8L"73vf#rȕSNvS䦭u.qGGԾ3oL;oJ VUj(rGNN`޽*&杜a6LNN-V/qmY?qvsbjS䦽u̻vf#9uʩE ?&NRGvԾtq?x% 3 ?&N̺k{H:'^λ? >S>|X.|:'t4sάۙ G9GĵR#BTf}mvf޽:'mt޽tq.0#wMrw}xaX?Zq!vzc^1Gtqrh{/vO'`;8;ݟpW,]ܟPKwD [‘fqDLZ}lgMSgEnvQSsbjG*m'`;3P@nnl"8;ۙSG;`;3p]z]{lgNkSk#wMrw}9޽3:r$qۙQNJw}uz]{lgF=8uIN3zǕk֩Jrw}ԑ&9>ΌzpW˯ݽN=USkb (S]mK(A\(rBCUhCsJ9ir(M ""׮^XtCf>6SPbINyAD9he{lgF=x}(9uKn-ztUJbkUbc}xY .תNP}m#uɩw5Pvm1÷*RUz*ô}mrYӡ#]CZYGJR[hZսoXk:-PBdk`}ӻ.9]is>}WINM]{ކttw@ OP G`;3Xz}s>}WINM}ކtt+'گ$>Όz]z} P |.`;3Ǻ;`;3Ǻ;~y̨%qP·*RۙQ^_Nrw %꜡:#ۙцĭiG^[VUN%fkUۙц˥ĭi/hC:%Ų8֣*ht89sX:'i2{lghCo\UWuX:'=R vG3cSWqdo}kDȩEzļݭF}9rjۙajpqniDȩ}^. @ vb {u׈J߇WWoYa:'<#P'lC Ga9P01cpJ`;3Ps9a%>i>:'L.> ch 4%cn~B͸zsë7w¢UulgF=߇ű(A\}bI;p%}T9Q˙8? >3lg[fvf&>Ό6y{P5 G:1|(Zeh˙%\7 e]3;9rb sr0Ǵ@%9qvhNO9JZeՖX UCc}m;9>q(qvǴi'gȬ8;RۙnrIri˙͔p,R/{39:'jۙQ9J6{"PbvYvf`;3;'g>N x-PBg'e=D¼vfarhrC`3y%-2'Ύc}Pv;JT1̢Uu DGzlgF=]~-db-3 І͔84 En}mđs|lgG%Ы:Ly^@OmvH3~ylgFxə҉8ab tCPs'(t"NztA4{lgF=vrB=x}߇a,# b'gI c7c̨NOBW9mcJ9AT[`;3˙3,>N x8P9%:9/ j.;PB_lgFwy9vfQ}^ZնpB'>@zJXն"B4{ql}/ K'熜jg)n#ۙQwy9qP^99A͝ (!k NΒvf5s|}/﫹s vcNQqvp`;30sYsIJ8`J\lgF=859N\+k[߇as .L.DއWj.;9@%9q=9R>|Ps+Nj.;9Xbcq=9Rg#ۙ1P[58u}mnu|lgF=(9u䮽3 u;9-q~''n-׮ > CE 01csWsmU5Y[5j.n,1ɱsۙ~''Nx3 N`;ayr@N!^>:c0\g ur}5}3 >Qz=:9D‘f̆k,>N xԻ}5n,q5= O>Ό6;9>qr﫹h׼5SGWQ{Wܿ_/_Όц:ުũhuuC͝vf6p*㭚~>謧.?zz4ʺ(AE=F9Qr(G9Qr>輨(G9w輨(oHz5 ?ź(G9:/1Qr(G9Qr(AE=F9Q؎輨esrv;iesr]][Cn:/quٜ\аwNY49~y>qyцDVi]E(HK` Wuu9ob輨zxC':JD" L΋zHX%輨Ǻ2-N%BϜ9XiJ "b}.q"MCH3C\nyQup݌˫_ #PWeTERx @Evr|;9Kr'Yeq%}Fĕn4Wvbol:/:(۾RUܴ @E0%8J}? @EǸ~bv>Cȁ"azlݮݧzt^ty:"7-nS:/pZĵREUI}yц}yQ}yQ~)![87{s|΋z.G+Z9PB>輨zu9%:‘f}yQQ@cQ}Z @m8^m-G ת.NĉUԆ8תnM P҉8Cx_VuPNZխiJScH![_/z?] @CȁfqDi8Щr#ډ8k'pG%niD @Cȁ"azl4SXF/\#b:B cp+iE4"}MNE%i]\I&N8"7S!@OmM4S+t*pJ(笿76i;9Kr'Y>6@S}X6fЩhC~7Ij GũYprmxcJ&N_/k4(G9w輨(oHz5 ?ź(G9:/1Qr(G9Qr(AE=F9Q؎輨esr**** ENDJOB -- End Current Job (Process) ** ** Function: ** Terminate the current process by performing a system reset ** Inputs: -none- ** Outputs: N/A ** Registes affected: N/A ** Routines called: -none- ** Special error conditions: -none- * .globl endjob .text endjob: clr d0 trap #2 .end **** CRLF Output ** ** Function: ** Print and on CON: ** Inputs: -none- ** Outputs: -none- ** Registers affected: -none- ** Routines called: COUT ** Special error conditions: -none- * .globl crlf .globl cout .text crlf: move.l d1,-(a7) * save d1 moveq #$0d,d1 jsr cout * moveq #$0a,d1 jsr cout * move.l (a7)+,d1 * restore d1 rts .end **** COUT -- Console Output ** ** Function: ** Output character in D1.B to CON: ** Inputs: D1.B == character to output ** Outputs: -none- (character is output) ** Registers affected: -none- ** Routines called: -none- ** Special error conditions: -none- * .globl cout .text cout: movem.l d0-d1,-(a7) * save d0 and d1 moveq #2,d0 trap #2 * output character movem.l (a7)+,d0-d1 rts .end **** SORT -- Sort Array of Strings ** ** Function: ** SORT sorts the set of fixed length records according to ** the control information in the Sort Specification Block (SSB) ** pointed to by D1. ** Inputs: D1.L points to SSB ** Outputs: -none- (records sorted) ** Registers affected: -none- ** Routines called: compare routine (SSB) ** Special Error Conditions: -none- ** ** SSB Format: ** ** Long: starting address of first record ** Word: number of records to sort ** Word: Size of each record ** Long: Address of compare routine ** Long: -reserved- * .globl sort .globl cmpa12 .text sort: movem.l d0-d7/a0-a6,-(a7) * save registers move.l d1,a1 * ptr to ssb move.l (a1),a2 * start of records move 4(a1),d6 * number of records cmpi #1,d6 ble sortx * if .le. 1 record mulu 6(a1),d6 * lba+1; inner loop limit add.l a2,d6 move.l d6,a5 sub 6(a1),a5 * (lba+1)-recsize move.l a5,d5 * outer loop limit * begin inner loop sort1: move.l a2,a3 add 6(a1),a3 * compare sort2: move.l 8(a1),a6 * compare routine jsr (a6) ble sort4 * no need to swap * swap entries move.l a2,a5 * item 1 move.l a3,a6 * item 2 move 6(a1),d3 * length in bytes subq #1,d3 sort3: move.b (a5),d4 * swap bytes move.b (a6),(a5)+ move.b d4,(a6)+ dbra d3,sort3 * loop for all of entry * end of inner loop sort4: add 6(a1),a3 cmpa.l d6,a3 blt sort2 * end of outer loop add 6(a1),a2 cmpa.l d5,a2 blt sort1 * sortx: movem.l (a7)+,d0-d7/a0-a6 rts * *** cmpa12 -- compare 12 bytes ascending (on word boundary) * cmpa12: movem.l d2/a2-a3,-(a7) * save registers cmpm.l (a3)+,(a2)+ bne cmpx * not equal cmpm.l (a3)+,(a2)+ bne cmpx * not equal cmpm.l (a3)+,(a2)+ cmpx: movem.l (a7)+,d2/a2-a3 rts * .end **** MD5DC -- convert binary value to decimal string ** ** Function: ** Store the contents of D1.W as 5 decimal characters in memory ** location (5 bytes) pointed to by D0.L ** Inputs: D0.L == pointer to 5-byte buffer ** D1.W == value to convert ** Outputs: D0.L == pointer to byte following buffer ** Registers affected: D0.L ** Routines called: -none- ** Special error conditions: -none- * .globl md5dc .text md5dc: movem.l d1-d2/a1,-(a7) * save registers move.l d0,a1 addq #5,a1 moveq #4,d2 md5dc1: ext.l d1 * clear upper divu #10,d1 * get last digit swap d1 add #$30,d1 * convert to ascii move.b d1,-(a1) * and store swap d1 dbra d2,md5dc1 * loop for 5 digits * moveq #3,d2 * get rid of leading zeros md5dc2: move.b (a1),d1 cmpi.b #$30,d1 bne md5dc3 * if not ZERO move.b #$20,(a1)+ * change to blank dbra d2,md5dc2 * md5dc3: addq #5,d0 movem.l (a7)+,d1-d2/a1 rts * .end **** OPTSCN -- options scanner ** ** Function: ** Scan command line for options and set flags in option table ** Inputs: D0.l == pointer to command line (assumed capitalized) ** D1.l == pointer to options table ** D2.l == pointer to input FCB (0 indicates none) ** D3.l == pointer to output FCB (0 indicates none) ** Outputs: D0.l == pointer to end of parsed command line (+1) ** Registers affected: D0.l, ( options table ) ** Routines called: OPTSET, MAKEFCB ** Special error conditions: D1.l=0 implies error in options. ** Error msg printed to CON: if: ** o bad delimiter on line ** o bad file name ** o input re-direct not allowed ** o output re-direct not allowed * ** last mod: 14feb85 jmk /make ptr into longword/ * * .globl optscn .globl optset .globl makefcb .text optscn: move.l a0,-(a7) move.l d1,-(a7) move.l d0,a0 * ptr to line * optsc1: move.b (a0)+,d0 cmpi.b #0,d0 beq optscx * end of line cmpi.b #' ',d0 beq optsc1 * ignore blanks cmpi.b #'-',d0 beq optsco * option flag cmpi.b #'$',d0 beq optsco * alternate option flag cmpi.b #'*',d0 * test for wildcard beq optsc2 * treat as A-Z (filespec) cmpi.b #'<',d0 beq optinr * input re-direct cmpi.b #'>',d0 beq optotr * output re-direct cmpi.b #'A',d0 blt opterm * bad character cmpi.b #'Z',d0 bgt opterm * bad character * ** it's a file name * optsc2: move.l d2,d1 * file FCB beq optfne * hey, not legal move.l a0,d0 subq.l #1,d0 * pointer to beginning of name jsr makefcb * make file name into FCB move.l d0,a0 tst.l d1 bne optsc1 * no problem optfne: move.l #bdfnm,d1 bra opter1 * * optinr: move.l d3,d1 * ptr to input fcb beq optie * hey, not legal move.l a0,d0 jsr makefcb move.l d0,a0 tst.l d1 bne optsc1 * no problem optie: move.l #bdinf,d1 bra opter1 * * optotr: move.l d4,d1 * prt to output fcb beq optoe * hey, not legal move.l a0,d0 jsr makefcb move.l d0,a0 tst.l d1 bne optsc1 * no problem optoe: move.l #bdotf,d1 bra opter1 * * optsco: move.l a0,d0 * option pointer move.l (a7),d1 * table pointer jsr optset move.l d0,a0 tst.l d1 beq opterr * if bad option bra optsc1 * * opterm: subq.l #1,a0 * point to bad character opterr: * A0.L points to bad option move.b (a0),optbd move.l #optdm,d1 opter1: moveq #9,d0 trap #2 * print error msg clr.l (a7) * return error * optscx: move.l (a7)+,d1 move.l a0,d0 * pointer to end of line move.l (a7)+,a0 rts * * .data cr: .equ 13 lf: .equ 10 * optdm: .dc.b ' Illegal option [x]',cr,lf,'$' optbd: .equ optdm+19 * bdfnm: .dc.b ' Bad file spec.',cr,lf,'$' bdinf: .dc.b ' Illegal input re-direct',cr,lf,'$' bdotf: .dc.b ' Illegal output re-diredt',cr,lf,'$' * * .end **** OPTSET -- option set ** ** Function: ** Set options in option table according to options in command ** line. Terminate at first delimiter (i.e. not A-Z) ** Inputs: D0.l == pointer to first option ** D1.l == pointer to table ** Outputs: D0.l == pointer to delimiter ** Registers affected: D0.l, (table) ** Routines called: -none- ** Special error conditions: D1.l=0 indicates error, then D0.l points ** to invalid option. ** ** Option table format: The options table consists of a series of ** byte pairs as "option letter, occurance value". ** i.e. ** .dc.b 'A',0 ** .dc.b 'B',0 ** etc, ** .dc.b 0,0 * terminator ** ** If an option is encountered, the least-significant bit of the ** occurance value is *TOGGLED*. ** * .globl optset .text optset: movem.l d1/a0-a1,-(a7) move.l d0,a0 * optst1: move.b (a0),d2 * get option cmpi.b #'A',d2 blt optstx * delimiter cmpi.b #'Z',d2 bgt optstx * delimiter move.l d1,a1 * table pointer optst2: tst.b (a1) bne optst3 * if not end of table clr.l d1 * bad option bra optstx * optst3: cmp.b (a1),d2 beq optst4 * bingo! addq.l #2,a1 bra optst2 * keep looking optst4: addq.l #1,a1 eori.b #1,(a1) * toggle value * addq.l #1,a0 * go to next character in line bra optst1 * optstx: move.l a0,d0 * pointer to err or delimiter movem.l (a7)+,d2/a0-a1 rts * .end **** makefcb -- make file control block ** ** Function: ** Convert text string into FCB. ** Inputs: D0.l == pointer to text string ** D1.l == pointer to FCB ** Outputs: D0.l == points to delimiter after file name ** Registers affected: D0.l, D1.l (if error), (FCB buffer) ** Routines called: CAPS ** Special error conditions: D1.l=0 implies error, then D0.l ** points to bad character. * ** last mod: 14feb85 jmk /fix eol check/ * * .globl makefcb .globl caps .text makefcb: movem.l a0-a2,-(a7) move.l d1,a2 move.l d1,a1 move.l d0,a0 moveq #7,d0 mkf1: clr (a1)+ * clear FCB dbra d0,mkf1 move.l d1,a1 move.l #' ',(a1) move.l #' ',4(a1) move.l #' ',8(a1) clr.b (a1) * cmpi.b #':',1(a0) bne mkf3 * if not disk drive # move.b (a0),d1 * get drive letter jsr caps subi.b #$40,d1 * convert to drive # (1-16) move.b d1,(a1) addq.l #2,a0 cmpi.b #' ',(a0) bgt mkf3 * more to file name addq #1,a0 * ptr to after delimiter addq #1,a1 * ptr to name in FCB move #10,d1 * special case of 'd:' with mkf2: move.b #'?',(a1)+ * no file name, must fill FCB dbra d1,mkf2 * with '?' wild cards bra mkx * mkf3: addq.l #1,a1 * start of file name moveq #7,d0 mkf4: move.b (a0)+,d1 * get char. of name jsr caps cmpi.b #'0',d1 blt mkf5 * if delimiter mkf4x: move.b d1,(a1)+ dbra d0,mkf4 * pick up to 8 chars. move.b (a0)+,d1 bra mkf6 * better be . or delimiter * mkf5: cmpi.b #'*',d1 beq mkf7 * wild card cmpi.b #'?',d1 beq mkf4x * treat ? as part of name mkf6: cmpi.b #'.',d1 beq mkf8 * end of fname cmpi.b #' ',d1 bgt mkerr * to many chars in fname bra mkx * finished * mkf7: * found '*' wild card move.b #'?',(a1)+ * file name with ? chars dbra d0,mkf7 move.b (a0)+,d1 bra mkf6 * better be . or delimiter * mkf8: move.l a2,a1 * now for file type add #9,a1 * point to extension in fcb moveq #2,d0 mkf9: move.b (a0)+,d1 * get char jsr caps cmpi.b #'0',d1 blt mkf10 * if delimiter of some type mkf9x: move.b d1,(a1)+ dbra d0,mkf9 * loop for up to 3 chars mkf9y: move.b (a0)+,d1 cmpi.b #' ',d1 bgt mkerr * extension too long bra mkx * mkf10: cmpi.b #'?',d1 beq mkf9x * treat ? as part of type cmpi.b #'*',d1 bne mkf12 * if not wild card mkf11: move.b #'?',(a1)+ * fill with '?' dbra d0,mkf11 bra mkf9y * better end here * mkf12: cmpi.b #0,d1 beq mkx * if end of cmd line cmpi.b #' ',d1 beq mkx * the end * mkerr: clr.l d1 * indicate error bra mkx1 * mkx: move.l a2,d1 * normal exit mkx1: subq #1,a0 move.l a0,d0 movem.l (a7)+,a0-a2 rts * .end **** CAPS -- Capitalize Character ** ** Function: ** Capitalize the ASCII character in D1.b if it is a ** lower-case alphabetic (a-z); otherwise return unchanged. ** Only the lower 7 bits are considered. The most ** significant bit is cleared. ** Inputs: D1.b == character to capitalize ** Outputs: D1.b == capitalized character ** Registers affected: D1.b ** Routines called: -none- ** Special error conditions: -none- * .globl caps .text caps: andi.b #$7f,d1 * mask off sign bit cmpi.b #'a',d1 blt capsx * not a-z cmpi.b #'z',d1 bgt capsx * not a-z andi.b #$5f,d1 * a-z ==> A-Z * capsx: rts .end lo68 -r -s sd.68k sd.o endjob.o crlf.o cout.o sort.o md5dc.o optscn.o optset.o makefcb.o caps.o