1958
|
1 ******************************************************************
|
|
2 * dirsort - Directory sorting utility
|
|
3 *
|
|
4 * This is an asm version of a Basic09 directory sort
|
|
5 * that was published in a Coco newsletter.
|
|
6 * Original and ml routine by Robert Gault, Nov. 2005
|
|
7 *
|
|
8 * The program uses a version of Shellsort published
|
|
9 * in a May 1983, BYTE article by Terry Barron and
|
|
10 * George Diehr (both at University of Washington)
|
|
11 *
|
|
12 * Edt/Rev YYYY/MM/DD Modified by
|
|
13 * Comment
|
|
14 * -------------------------------------------------------------
|
|
15 * 1 2005/12/19 Robert Gault
|
|
16 * Very fast and fairly simple
|
|
17 * 2 2005/12/20 Robert Gault
|
|
18 * Minor change of use /dd/defs/defsfile to use defsfile. The first
|
|
19 * was for my OS-9 system. The current one is for the NitrOS-9
|
|
20 * project.
|
|
21
|
|
22 NAM dirsort
|
|
23 * This ensures the assembler knows predefined OS-9 terms
|
|
24 IFP1
|
|
25 USE defsfile
|
|
26 ENDC
|
|
27
|
|
28 * If you want built-in help change the next line.
|
|
29 HELP SET FALSE
|
|
30
|
|
31 TyLg SET Prgrm+Objct program object code
|
|
32 * Re-entrant means multiple users possible
|
|
33 AtRev SET ReEnt+Rev re-entrant, revision 1
|
|
34 Rev SET 1
|
|
35
|
|
36 * Create module header, needed by all OS-9 modules
|
|
37 MOD Eom,Name,TyLg,AtRev,Start,Size
|
|
38 * Data area
|
|
39 DPptr RMB 2 pointer to our direct page
|
|
40 dirsize RMB 2 size of the directory less 64 bytes
|
|
41 count RMB 2 number of directory entries
|
|
42 entryI RMB 2 pointer to nameI
|
|
43 entryJ RMB 2 pointer to nameJ
|
|
44 entryID RMB 2 pointer to name(I+D)
|
|
45 Tx RMB 32 buffer for transfer
|
|
46 i RMB 2 index
|
|
47 j RMB 2 index
|
|
48 NminusD RMB 2 holds last value of FOR I/NEXT loop
|
|
49 path RMB 1 value for path to the directory
|
|
50 D RMB 2 shellsort constant
|
|
51 RMB 40
|
|
52 stack EQU .
|
|
53 Size EQU . This initial data space will be increased as OS-9
|
|
54 * assigns space in pages of 256 bytes. Initially the stack will
|
|
55 * not be here.
|
|
56 buffer EQU . This will be the start of the data array in memory
|
|
57 * to be requested from OS-9 as needed.
|
|
58
|
|
59 Name EQU *
|
|
60 FCS /dirsort/
|
|
61 FCB 1 edition number
|
|
62 * Ego stroking :) identifier
|
|
63 FCC /Written by Robert Gault, 2005/
|
|
64
|
|
65 * Default directory name, dot, or current directory
|
|
66 default FCB C$PERD,C$CR
|
|
67
|
|
68 * Solutions for N,2^INT(LN(N)) -1
|
|
69 * We don't need general logs just specifc values so
|
|
70 * they were pre-calculated
|
|
71 Dtable FDB 2,0
|
|
72 FDB 7,1
|
|
73 FDB 20,3
|
|
74 FDB 54,7
|
|
75 FDB 148,15
|
|
76 * If your directory has more entries than several hundred, you
|
|
77 * need to learn how to organize your disk/drive.
|
|
78 FDB 403,31
|
|
79 FDB 1096,63
|
|
80 * This next will exceed normal memory limits but is needed
|
|
81 * for values up to about 2000. We could just put $FFFF/32=
|
|
82 * 2047 but there are size checks in the code.
|
|
83 FDB 2980,127
|
|
84 DTEnd EQU *
|
|
85
|
|
86 Start EQU *
|
|
87 stu <DPptr save the direct page pointer
|
|
88 leas stack,u put the stack where we want it or it will be
|
|
89 * inside the directory buffer and crash the program.
|
|
90 cmpd #0 are there any parameters?
|
|
91 beq noprm
|
|
92 l1 lda ,x+ skip over spaces, if any
|
|
93 cmpa #C$SPAC
|
|
94 beq l1
|
|
95 cmpa #C$CR if only spaces, same as noprm
|
|
96 bne a1
|
|
97 noprm leax default,pcr point to default directory, dot
|
|
98 bra a9
|
|
99 IFNE HELP
|
|
100 a1 cmpa #'? if "?" then show syntax
|
|
101 lbeq syntax
|
|
102 cmpa #'- if attempt at options, syntax
|
|
103 lbeq syntax
|
|
104 leax -1,x
|
|
105 ELSE
|
|
106 a1 leax -1,x backstep to first character of directory
|
|
107 ENDC
|
|
108 a9 lda #%11000011 directory, single user access, update
|
|
109 os9 I$Open attempt to open a path to the directory
|
|
110 lbcs error
|
|
111 sta <path save the path #
|
|
112 ldb #SS.Size get the size of the directory
|
|
113 os9 I$GetStt size reported in regs X&U
|
|
114 cmpx #0 MSB of size
|
|
115 lbne Tlarge too big to sort
|
|
116 tfr u,d evaluate the size
|
|
117 cmpd #128 two entries other than .. and .
|
|
118 lblo getreal can't sort 1 item or less
|
|
119 subd #64 reduce size by 64 bytes for .. and .
|
|
120 std <dirsize save size in bytes
|
|
121 addd #Size we need current data + directory buffer
|
|
122 os9 F$Mem request space for the buffer
|
|
123 lbcs Tlarge can't get enough memory
|
|
124 lda <path recover path to the directory
|
|
125 ldx #0 MSB position
|
|
126 ldu #64 LSB, past the entries .. and .
|
|
127 os9 I$Seek skip over the entries
|
|
128 ldu <DPptr recover DP pointer
|
|
129 ldy <dirsize data size in bytes
|
|
130 leax buffer,u point to our buffer
|
|
131 os9 I$Read transfer the directory information to buffer
|
|
132 * Calculate the number of directory entries
|
|
133 * Divide size by 32 bytes per entry. INT(size/32)must=size/32 or
|
|
134 * the directory is corrupted. So, ignore remainder.
|
|
135 ldx #0 initialize counter
|
|
136 ldd <dirsize this does not include . and ..
|
|
137 IFNE H6309
|
|
138 lsrd
|
|
139 lsrd
|
|
140 lsrd
|
|
141 lsrd
|
|
142 lsrd
|
|
143 ELSE
|
|
144 lsra
|
|
145 rorb
|
|
146 lsra
|
|
147 rorb
|
|
148 lsra
|
|
149 rorb
|
|
150 lsra
|
|
151 rorb
|
|
152 lsra
|
|
153 rorb
|
|
154 ENDC
|
|
155 std <count
|
|
156 leax Dtable,pcr precalculated constants
|
|
157 leay DTEnd,pcr
|
|
158 pshs y
|
|
159 l3 cmpd ,x
|
|
160 bls a4 if fewer or equal # of entries get D
|
|
161 leax 4,x move to next table entry
|
|
162 cmpx ,s have we exhausted the table?
|
|
163 bne l3
|
|
164 leas 2,s restore the stack
|
|
165 lbra Tlarge should not be possible to get here in code
|
|
166 a4 leas 2,s restore the stack
|
|
167 ldd 2,x get shellsort D from table
|
|
168 std <D save working value
|
|
169 * Sort starts here
|
|
170 * Directory entries can't have duplicate names or the directory
|
|
171 * is corrupted. That means a<b is as good as a<=b when testing.
|
|
172 s2 ldd #1 initialize FOR/NEXT loop
|
|
173 std <i
|
|
174 ldd <count same as n in Basic09 program
|
|
175 subd <D
|
|
176 std <NminusD save value
|
|
177 * calculated pointer for entryID
|
|
178 s6 ldd <i FOR i=1 TO n-D STEP 1
|
|
179 addd <D get pointer for entry(i+D)
|
|
180 lbsr point get the pointer value
|
|
181 stx <entryID
|
|
182 tfr x,y
|
|
183 * calculate pointer for entryI
|
|
184 ldd <i
|
|
185 lbsr point
|
|
186 stx <entryI
|
|
187 * Compare the entry pointed to by regX against that for regY
|
|
188 lbsr compare is name(i) < name(i+D)
|
|
189 bcs s20
|
|
190 ldx <entryID
|
|
191 leay Tx,u shellsort swap name holder
|
|
192 lbsr movexy name(Tx)=name(i+D)
|
|
193 ldx <entryI
|
|
194 ldy <entryID
|
|
195 bsr movexy name(i+D)=name(i)
|
|
196 ldd <i
|
|
197 cmpd <D
|
|
198 bhi s4 this was a Basic09 IF/THEN
|
|
199 ldy <entryI inside the IF/THEN
|
|
200 leax Tx,u
|
|
201 bsr movexy name(i)=name(Tx)
|
|
202 bra s20 ends the IF/THEN
|
|
203 s4 ldd <i initialize FOR/NEXT loop
|
|
204 subd <D
|
|
205 std <j
|
|
206 s5 bsr point FOR j=i-D TO 1 STEP -D
|
|
207 stx <entryJ
|
|
208 tfr x,y
|
|
209 leax Tx,u
|
|
210 lbsr compare is entry(Tx) > entry(j)
|
|
211 bcc s10
|
|
212 ldd <j
|
|
213 addd <D name(j+D)
|
|
214 bsr point
|
|
215 tfr x,y
|
|
216 ldx <entryJ
|
|
217 bsr movexy name(j+D)=name(j)
|
|
218 ldd <j NEXT j
|
|
219 subd <D STEP -D
|
|
220 std <j
|
|
221 cmpd #1 stop if less than 1
|
|
222 bge s5
|
|
223 s10 leay Tx,u
|
|
224 ldd <j
|
|
225 addd <D
|
|
226 bsr point
|
|
227 exg x,y
|
|
228 bsr movexy name(j+D)=name(Tx)
|
|
229 s20 ldd <i NEXT i
|
|
230 addd #1 STEP +1
|
|
231 std <i
|
|
232 cmpd <NminusD
|
|
233 bls s6 stop if i>(n-D)
|
|
234 ldd <D D=D/2
|
|
235 IFNE H6309
|
|
236 lsrd
|
|
237 ELSE
|
|
238 lsra
|
|
239 rorb
|
|
240 ENDC
|
|
241 std <D
|
|
242 cmpd #1
|
|
243 lbhs s2 WHILE D>0
|
|
244 lda <path rewind to just after .. & .
|
|
245 ldx #0
|
|
246 ldu #64
|
|
247 os9 I$Seek
|
|
248 lda <path
|
|
249 ldu <DPptr
|
|
250 leax buffer,u write out sorted directory
|
|
251 ldy <dirsize
|
|
252 os9 I$Write
|
|
253 clrb
|
|
254 os9 F$Exit release memory, close paths, and return to OS-9
|
|
255
|
|
256 IFNE H6309
|
|
257 movexy ldw #32
|
|
258 tfm x+,y+
|
|
259 rts
|
|
260 ELSE
|
|
261 movexy ldb #16 move the entry pointed to in regX to
|
|
262 pshs b
|
|
263 sw1 ldd ,x++ that pointed to by regY
|
|
264 std ,y++
|
|
265 dec ,s if not finished, continue
|
|
266 bne sw1
|
|
267 puls b,pc
|
|
268 ENDC
|
|
269
|
|
270 * Converts an index in regD to a memory offset in regX
|
|
271 * This could easily overflow but there are size checks
|
|
272 * in the above code so there is no overflow test.
|
|
273 point leax buffer,u
|
|
274 subd #1
|
|
275 IFNE H6309
|
|
276 lsld
|
|
277 lsld
|
|
278 lsld
|
|
279 lsld
|
|
280 lsld
|
|
281 ELSE
|
|
282 lslb
|
|
283 rola
|
|
284 lslb
|
|
285 rola
|
|
286 lslb
|
|
287 rola
|
|
288 lslb
|
|
289 rola
|
|
290 lslb
|
|
291 rola
|
|
292 ENDC
|
|
293 leax d,x
|
|
294 rts
|
|
295
|
|
296 compare ldb #29 size of name field
|
|
297 pshs b save counter
|
|
298 cloop ldb ,y+ get character
|
|
299 lda ,x+ get character
|
|
300 beq c1 if deleted go
|
|
301 tstb
|
|
302 beq c2 if deleted go
|
|
303 tsta
|
|
304 bmi c5 if last character go
|
|
305 tstb
|
|
306 bmi c6 if last character go
|
|
307 pshs b
|
|
308 cmpa ,s+
|
|
309 beq c4 if equal, test next character
|
|
310 bra cx
|
|
311 c1 clra
|
|
312 bra cx return +
|
|
313 c2 coma
|
|
314 bra cx return -
|
|
315 c3 anda #$7f
|
|
316 andb #$7f
|
|
317 pshs b
|
|
318 cmpa ,s+
|
|
319 rts
|
|
320 c5 bsr c3
|
|
321 beq c2
|
|
322 bra cx
|
|
323 c6 bsr c3
|
|
324 beq c1
|
|
325 bra cx return result
|
|
326 c4 dec ,s
|
|
327 bne cloop
|
|
328 clra should not be able to get here in code
|
|
329 cx puls b,pc return result
|
|
330
|
|
331 error leax nodir,pcr
|
|
332 ldy #endnd-nodir
|
|
333 write lda #1 screen
|
|
334 os9 I$Write
|
|
335 clrb
|
|
336 os9 F$Exit
|
|
337 nodir EQU *
|
|
338 FCC /Directory does not exist!/
|
|
339 FCB C$CR,C$LF
|
|
340 endnd EQU *
|
|
341
|
|
342 Tlarge leax big,pcr
|
|
343 ldy #endbig-big
|
|
344 bra write
|
|
345 big EQU *
|
|
346 FCC /Either the directory is too large or there is insufficient /
|
|
347 FCC /memory./
|
|
348 FCB C$CR,C$LF
|
|
349 endbig EQU *
|
|
350
|
|
351 getreal leax huh,pcr
|
|
352 ldy #endhuh-huh
|
|
353 clr ,-s
|
|
354 bra write
|
|
355 huh EQU *
|
|
356 FCC /Get real! You can't sort less than 2 items./
|
|
357 FCB C$CR,C$LF
|
|
358 endhuh EQU *
|
|
359
|
|
360 IFNE HELP
|
|
361 syntax leax usage,pcr
|
|
362 ldy #enduse-usage
|
|
363 clr ,-s
|
|
364 lbra write
|
|
365 usage FCC /USAGE: dirsort will sort any directory. If no directory/
|
|
366 FCB C$CR,C$LF
|
|
367 FCC / name is given, the current directory will be sorted./
|
|
368 FCB C$CR,C$LF
|
|
369 FCC /EX: dirsort dirsort . dirsort ../
|
|
370 FCB C$CR,C$LF
|
|
371 FCC " dirsort /dd/cmds"
|
|
372 FCB C$CR,C$LF
|
|
373 enduse EQU *
|
|
374 ENDC
|
|
375
|
|
376 EMOD
|
|
377 Eom EQU *
|
|
378 END
|