Mercurial > hg > Members > kono > nitros9-code
changeset 1958:df97c336e737
Converted to UNIX terminators
author | robert |
---|---|
date | Wed, 21 Dec 2005 13:59:09 +0000 |
parents | 6b282e7c880f |
children | 3d26c3a92170 |
files | level1/cmds/dirsort.asm |
diffstat | 1 files changed, 378 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/level1/cmds/dirsort.asm Tue Dec 20 23:18:33 2005 +0000 +++ b/level1/cmds/dirsort.asm Wed Dec 21 13:59:09 2005 +0000 @@ -1,1 +1,378 @@ -****************************************************************** * dirsort - Directory sorting utility * * This is an asm version of a Basic09 directory sort * that was published in a Coco newsletter. * Original and ml routine by Robert Gault, Nov. 2005 * * The program uses a version of Shellsort published * in a May 1983, BYTE article by Terry Barron and * George Diehr (both at University of Washington) * * Edt/Rev YYYY/MM/DD Modified by * Comment * ------------------------------------------------------------- * 1 2005/12/19 Robert Gault * Very fast and fairly simple * 2 2005/12/20 Robert Gault * Minor change of use /dd/defs/defsfile to use defsfile. The first * was for my OS-9 system. The current one is for the NitrOS-9 * project. NAM dirsort * This ensures the assembler knows predefined OS-9 terms IFP1 USE defsfile ENDC * If you want built-in help change the next line. HELP SET FALSE TyLg SET Prgrm+Objct program object code * Re-entrant means multiple users possible AtRev SET ReEnt+Rev re-entrant, revision 1 Rev SET 1 * Create module header, needed by all OS-9 modules MOD Eom,Name,TyLg,AtRev,Start,Size * Data area DPptr RMB 2 pointer to our direct page dirsize RMB 2 size of the directory less 64 bytes count RMB 2 number of directory entries entryI RMB 2 pointer to nameI entryJ RMB 2 pointer to nameJ entryID RMB 2 pointer to name(I+D) Tx RMB 32 buffer for transfer i RMB 2 index j RMB 2 index NminusD RMB 2 holds last value of FOR I/NEXT loop path RMB 1 value for path to the directory D RMB 2 shellsort constant RMB 40 stack EQU . Size EQU . This initial data space will be increased as OS-9 * assigns space in pages of 256 bytes. Initially the stack will * not be here. buffer EQU . This will be the start of the data array in memory * to be requested from OS-9 as needed. Name EQU * FCS /dirsort/ FCB 1 edition number * Ego stroking :) identifier FCC /Written by Robert Gault, 2005/ * Default directory name, dot, or current directory default FCB C$PERD,C$CR * Solutions for N,2^INT(LN(N)) -1 * We don't need general logs just specifc values so * they were pre-calculated Dtable FDB 2,0 FDB 7,1 FDB 20,3 FDB 54,7 FDB 148,15 * If your directory has more entries than several hundred, you * need to learn how to organize your disk/drive. FDB 403,31 FDB 1096,63 * This next will exceed normal memory limits but is needed * for values up to about 2000. We could just put $FFFF/32= * 2047 but there are size checks in the code. FDB 2980,127 DTEnd EQU * Start EQU * stu <DPptr save the direct page pointer leas stack,u put the stack where we want it or it will be * inside the directory buffer and crash the program. cmpd #0 are there any parameters? beq noprm l1 lda ,x+ skip over spaces, if any cmpa #C$SPAC beq l1 cmpa #C$CR if only spaces, same as noprm bne a1 noprm leax default,pcr point to default directory, dot bra a9 IFNE HELP a1 cmpa #'? if "?" then show syntax lbeq syntax cmpa #'- if attempt at options, syntax lbeq syntax leax -1,x ELSE a1 leax -1,x backstep to first character of directory ENDC a9 lda #%11000011 directory, single user access, update os9 I$Open attempt to open a path to the directory lbcs error sta <path save the path # ldb #SS.Size get the size of the directory os9 I$GetStt size reported in regs X&U cmpx #0 MSB of size lbne Tlarge too big to sort tfr u,d evaluate the size cmpd #128 two entries other than .. and . lblo getreal can't sort 1 item or less subd #64 reduce size by 64 bytes for .. and . std <dirsize save size in bytes addd #Size we need current data + directory buffer os9 F$Mem request space for the buffer lbcs Tlarge can't get enough memory lda <path recover path to the directory ldx #0 MSB position ldu #64 LSB, past the entries .. and . os9 I$Seek skip over the entries ldu <DPptr recover DP pointer ldy <dirsize data size in bytes leax buffer,u point to our buffer os9 I$Read transfer the directory information to buffer * Calculate the number of directory entries * Divide size by 32 bytes per entry. INT(size/32)must=size/32 or * the directory is corrupted. So, ignore remainder. ldx #0 initialize counter ldd <dirsize this does not include . and .. IFNE H6309 lsrd lsrd lsrd lsrd lsrd ELSE lsra rorb lsra rorb lsra rorb lsra rorb lsra rorb ENDC std <count leax Dtable,pcr precalculated constants leay DTEnd,pcr pshs y l3 cmpd ,x bls a4 if fewer or equal # of entries get D leax 4,x move to next table entry cmpx ,s have we exhausted the table? bne l3 leas 2,s restore the stack lbra Tlarge should not be possible to get here in code a4 leas 2,s restore the stack ldd 2,x get shellsort D from table std <D save working value * Sort starts here * Directory entries can't have duplicate names or the directory * is corrupted. That means a<b is as good as a<=b when testing. s2 ldd #1 initialize FOR/NEXT loop std <i ldd <count same as n in Basic09 program subd <D std <NminusD save value * calculated pointer for entryID s6 ldd <i FOR i=1 TO n-D STEP 1 addd <D get pointer for entry(i+D) lbsr point get the pointer value stx <entryID tfr x,y * calculate pointer for entryI ldd <i lbsr point stx <entryI * Compare the entry pointed to by regX against that for regY lbsr compare is name(i) < name(i+D) bcs s20 ldx <entryID leay Tx,u shellsort swap name holder lbsr movexy name(Tx)=name(i+D) ldx <entryI ldy <entryID bsr movexy name(i+D)=name(i) ldd <i cmpd <D bhi s4 this was a Basic09 IF/THEN ldy <entryI inside the IF/THEN leax Tx,u bsr movexy name(i)=name(Tx) bra s20 ends the IF/THEN s4 ldd <i initialize FOR/NEXT loop subd <D std <j s5 bsr point FOR j=i-D TO 1 STEP -D stx <entryJ tfr x,y leax Tx,u lbsr compare is entry(Tx) > entry(j) bcc s10 ldd <j addd <D name(j+D) bsr point tfr x,y ldx <entryJ bsr movexy name(j+D)=name(j) ldd <j NEXT j subd <D STEP -D std <j cmpd #1 stop if less than 1 bge s5 s10 leay Tx,u ldd <j addd <D bsr point exg x,y bsr movexy name(j+D)=name(Tx) s20 ldd <i NEXT i addd #1 STEP +1 std <i cmpd <NminusD bls s6 stop if i>(n-D) ldd <D D=D/2 IFNE H6309 lsrd ELSE lsra rorb ENDC std <D cmpd #1 lbhs s2 WHILE D>0 lda <path rewind to just after .. & . ldx #0 ldu #64 os9 I$Seek lda <path ldu <DPptr leax buffer,u write out sorted directory ldy <dirsize os9 I$Write clrb os9 F$Exit release memory, close paths, and return to OS-9 IFNE H6309 movexy ldw #32 tfm x+,y+ rts ELSE movexy ldb #16 move the entry pointed to in regX to pshs b sw1 ldd ,x++ that pointed to by regY std ,y++ dec ,s if not finished, continue bne sw1 puls b,pc ENDC * Converts an index in regD to a memory offset in regX * This could easily overflow but there are size checks * in the above code so there is no overflow test. point leax buffer,u subd #1 IFNE H6309 lsld lsld lsld lsld lsld ELSE lslb rola lslb rola lslb rola lslb rola lslb rola ENDC leax d,x rts compare ldb #29 size of name field pshs b save counter cloop ldb ,y+ get character lda ,x+ get character beq c1 if deleted go tstb beq c2 if deleted go tsta bmi c5 if last character go tstb bmi c6 if last character go pshs b cmpa ,s+ beq c4 if equal, test next character bra cx c1 clra bra cx return + c2 coma bra cx return - c3 anda #$7f andb #$7f pshs b cmpa ,s+ rts c5 bsr c3 beq c2 bra cx c6 bsr c3 beq c1 bra cx return result c4 dec ,s bne cloop clra should not be able to get here in code cx puls b,pc return result error leax nodir,pcr ldy #endnd-nodir write lda #1 screen os9 I$Write clrb os9 F$Exit nodir EQU * FCC /Directory does not exist!/ FCB C$CR,C$LF endnd EQU * Tlarge leax big,pcr ldy #endbig-big bra write big EQU * FCC /Either the directory is too large or there is insufficient / FCC /memory./ FCB C$CR,C$LF endbig EQU * getreal leax huh,pcr ldy #endhuh-huh clr ,-s bra write huh EQU * FCC /Get real! You can't sort less than 2 items./ FCB C$CR,C$LF endhuh EQU * IFNE HELP syntax leax usage,pcr ldy #enduse-usage clr ,-s lbra write usage FCC /USAGE: dirsort will sort any directory. If no directory/ FCB C$CR,C$LF FCC / name is given, the current directory will be sorted./ FCB C$CR,C$LF FCC /EX: dirsort dirsort . dirsort ../ FCB C$CR,C$LF FCC " dirsort /dd/cmds" FCB C$CR,C$LF enduse EQU * ENDC EMOD Eom EQU * END \ No newline at end of file +****************************************************************** +* dirsort - Directory sorting utility +* +* This is an asm version of a Basic09 directory sort +* that was published in a Coco newsletter. +* Original and ml routine by Robert Gault, Nov. 2005 +* +* The program uses a version of Shellsort published +* in a May 1983, BYTE article by Terry Barron and +* George Diehr (both at University of Washington) +* +* Edt/Rev YYYY/MM/DD Modified by +* Comment +* ------------------------------------------------------------- +* 1 2005/12/19 Robert Gault +* Very fast and fairly simple +* 2 2005/12/20 Robert Gault +* Minor change of use /dd/defs/defsfile to use defsfile. The first +* was for my OS-9 system. The current one is for the NitrOS-9 +* project. + + NAM dirsort +* This ensures the assembler knows predefined OS-9 terms + IFP1 + USE defsfile + ENDC + +* If you want built-in help change the next line. +HELP SET FALSE + +TyLg SET Prgrm+Objct program object code +* Re-entrant means multiple users possible +AtRev SET ReEnt+Rev re-entrant, revision 1 +Rev SET 1 + +* Create module header, needed by all OS-9 modules + MOD Eom,Name,TyLg,AtRev,Start,Size +* Data area +DPptr RMB 2 pointer to our direct page +dirsize RMB 2 size of the directory less 64 bytes +count RMB 2 number of directory entries +entryI RMB 2 pointer to nameI +entryJ RMB 2 pointer to nameJ +entryID RMB 2 pointer to name(I+D) +Tx RMB 32 buffer for transfer +i RMB 2 index +j RMB 2 index +NminusD RMB 2 holds last value of FOR I/NEXT loop +path RMB 1 value for path to the directory +D RMB 2 shellsort constant + RMB 40 +stack EQU . +Size EQU . This initial data space will be increased as OS-9 +* assigns space in pages of 256 bytes. Initially the stack will +* not be here. +buffer EQU . This will be the start of the data array in memory +* to be requested from OS-9 as needed. + +Name EQU * + FCS /dirsort/ + FCB 1 edition number +* Ego stroking :) identifier + FCC /Written by Robert Gault, 2005/ + +* Default directory name, dot, or current directory +default FCB C$PERD,C$CR + +* Solutions for N,2^INT(LN(N)) -1 +* We don't need general logs just specifc values so +* they were pre-calculated +Dtable FDB 2,0 + FDB 7,1 + FDB 20,3 + FDB 54,7 + FDB 148,15 +* If your directory has more entries than several hundred, you +* need to learn how to organize your disk/drive. + FDB 403,31 + FDB 1096,63 +* This next will exceed normal memory limits but is needed +* for values up to about 2000. We could just put $FFFF/32= +* 2047 but there are size checks in the code. + FDB 2980,127 +DTEnd EQU * + +Start EQU * + stu <DPptr save the direct page pointer + leas stack,u put the stack where we want it or it will be +* inside the directory buffer and crash the program. + cmpd #0 are there any parameters? + beq noprm +l1 lda ,x+ skip over spaces, if any + cmpa #C$SPAC + beq l1 + cmpa #C$CR if only spaces, same as noprm + bne a1 +noprm leax default,pcr point to default directory, dot + bra a9 + IFNE HELP +a1 cmpa #'? if "?" then show syntax + lbeq syntax + cmpa #'- if attempt at options, syntax + lbeq syntax + leax -1,x + ELSE +a1 leax -1,x backstep to first character of directory + ENDC +a9 lda #%11000011 directory, single user access, update + os9 I$Open attempt to open a path to the directory + lbcs error + sta <path save the path # + ldb #SS.Size get the size of the directory + os9 I$GetStt size reported in regs X&U + cmpx #0 MSB of size + lbne Tlarge too big to sort + tfr u,d evaluate the size + cmpd #128 two entries other than .. and . + lblo getreal can't sort 1 item or less + subd #64 reduce size by 64 bytes for .. and . + std <dirsize save size in bytes + addd #Size we need current data + directory buffer + os9 F$Mem request space for the buffer + lbcs Tlarge can't get enough memory + lda <path recover path to the directory + ldx #0 MSB position + ldu #64 LSB, past the entries .. and . + os9 I$Seek skip over the entries + ldu <DPptr recover DP pointer + ldy <dirsize data size in bytes + leax buffer,u point to our buffer + os9 I$Read transfer the directory information to buffer +* Calculate the number of directory entries +* Divide size by 32 bytes per entry. INT(size/32)must=size/32 or +* the directory is corrupted. So, ignore remainder. + ldx #0 initialize counter + ldd <dirsize this does not include . and .. + IFNE H6309 + lsrd + lsrd + lsrd + lsrd + lsrd + ELSE + lsra + rorb + lsra + rorb + lsra + rorb + lsra + rorb + lsra + rorb + ENDC + std <count + leax Dtable,pcr precalculated constants + leay DTEnd,pcr + pshs y +l3 cmpd ,x + bls a4 if fewer or equal # of entries get D + leax 4,x move to next table entry + cmpx ,s have we exhausted the table? + bne l3 + leas 2,s restore the stack + lbra Tlarge should not be possible to get here in code +a4 leas 2,s restore the stack + ldd 2,x get shellsort D from table + std <D save working value +* Sort starts here +* Directory entries can't have duplicate names or the directory +* is corrupted. That means a<b is as good as a<=b when testing. +s2 ldd #1 initialize FOR/NEXT loop + std <i + ldd <count same as n in Basic09 program + subd <D + std <NminusD save value +* calculated pointer for entryID +s6 ldd <i FOR i=1 TO n-D STEP 1 + addd <D get pointer for entry(i+D) + lbsr point get the pointer value + stx <entryID + tfr x,y +* calculate pointer for entryI + ldd <i + lbsr point + stx <entryI +* Compare the entry pointed to by regX against that for regY + lbsr compare is name(i) < name(i+D) + bcs s20 + ldx <entryID + leay Tx,u shellsort swap name holder + lbsr movexy name(Tx)=name(i+D) + ldx <entryI + ldy <entryID + bsr movexy name(i+D)=name(i) + ldd <i + cmpd <D + bhi s4 this was a Basic09 IF/THEN + ldy <entryI inside the IF/THEN + leax Tx,u + bsr movexy name(i)=name(Tx) + bra s20 ends the IF/THEN +s4 ldd <i initialize FOR/NEXT loop + subd <D + std <j +s5 bsr point FOR j=i-D TO 1 STEP -D + stx <entryJ + tfr x,y + leax Tx,u + lbsr compare is entry(Tx) > entry(j) + bcc s10 + ldd <j + addd <D name(j+D) + bsr point + tfr x,y + ldx <entryJ + bsr movexy name(j+D)=name(j) + ldd <j NEXT j + subd <D STEP -D + std <j + cmpd #1 stop if less than 1 + bge s5 +s10 leay Tx,u + ldd <j + addd <D + bsr point + exg x,y + bsr movexy name(j+D)=name(Tx) +s20 ldd <i NEXT i + addd #1 STEP +1 + std <i + cmpd <NminusD + bls s6 stop if i>(n-D) + ldd <D D=D/2 + IFNE H6309 + lsrd + ELSE + lsra + rorb + ENDC + std <D + cmpd #1 + lbhs s2 WHILE D>0 + lda <path rewind to just after .. & . + ldx #0 + ldu #64 + os9 I$Seek + lda <path + ldu <DPptr + leax buffer,u write out sorted directory + ldy <dirsize + os9 I$Write + clrb + os9 F$Exit release memory, close paths, and return to OS-9 + + IFNE H6309 +movexy ldw #32 + tfm x+,y+ + rts + ELSE +movexy ldb #16 move the entry pointed to in regX to + pshs b +sw1 ldd ,x++ that pointed to by regY + std ,y++ + dec ,s if not finished, continue + bne sw1 + puls b,pc + ENDC + +* Converts an index in regD to a memory offset in regX +* This could easily overflow but there are size checks +* in the above code so there is no overflow test. +point leax buffer,u + subd #1 + IFNE H6309 + lsld + lsld + lsld + lsld + lsld + ELSE + lslb + rola + lslb + rola + lslb + rola + lslb + rola + lslb + rola + ENDC + leax d,x + rts + +compare ldb #29 size of name field + pshs b save counter +cloop ldb ,y+ get character + lda ,x+ get character + beq c1 if deleted go + tstb + beq c2 if deleted go + tsta + bmi c5 if last character go + tstb + bmi c6 if last character go + pshs b + cmpa ,s+ + beq c4 if equal, test next character + bra cx +c1 clra + bra cx return + +c2 coma + bra cx return - +c3 anda #$7f + andb #$7f + pshs b + cmpa ,s+ + rts +c5 bsr c3 + beq c2 + bra cx +c6 bsr c3 + beq c1 + bra cx return result +c4 dec ,s + bne cloop + clra should not be able to get here in code +cx puls b,pc return result + +error leax nodir,pcr + ldy #endnd-nodir +write lda #1 screen + os9 I$Write + clrb + os9 F$Exit +nodir EQU * + FCC /Directory does not exist!/ + FCB C$CR,C$LF +endnd EQU * + +Tlarge leax big,pcr + ldy #endbig-big + bra write +big EQU * + FCC /Either the directory is too large or there is insufficient / + FCC /memory./ + FCB C$CR,C$LF +endbig EQU * + +getreal leax huh,pcr + ldy #endhuh-huh + clr ,-s + bra write +huh EQU * + FCC /Get real! You can't sort less than 2 items./ + FCB C$CR,C$LF +endhuh EQU * + + IFNE HELP +syntax leax usage,pcr + ldy #enduse-usage + clr ,-s + lbra write +usage FCC /USAGE: dirsort will sort any directory. If no directory/ + FCB C$CR,C$LF + FCC / name is given, the current directory will be sorted./ + FCB C$CR,C$LF + FCC /EX: dirsort dirsort . dirsort ../ + FCB C$CR,C$LF + FCC " dirsort /dd/cmds" + FCB C$CR,C$LF +enduse EQU * + ENDC + + EMOD +Eom EQU * + END