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