summaryrefslogtreecommitdiff
path: root/v4.0/src/CMD/SORT
diff options
context:
space:
mode:
authorGravatar Mark Zbikowski2024-04-25 21:24:10 +0100
committerGravatar Microsoft Open Source2024-04-25 22:32:27 +0000
commit2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch)
tree80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/CMD/SORT
parentMerge pull request #430 from jpbaltazar/typoptbr (diff)
downloadms-dos-main.tar.gz
ms-dos-main.tar.xz
ms-dos-main.zip
MZ is back!HEADmain
Diffstat (limited to 'v4.0/src/CMD/SORT')
-rw-r--r--v4.0/src/CMD/SORT/MAKEFILE36
-rw-r--r--v4.0/src/CMD/SORT/SORT.ASM1000
-rw-r--r--v4.0/src/CMD/SORT/SORT.LNK4
-rw-r--r--v4.0/src/CMD/SORT/SORT.SKL12
-rw-r--r--v4.0/src/CMD/SORT/SORTMES.ASM85
5 files changed, 1137 insertions, 0 deletions
diff --git a/v4.0/src/CMD/SORT/MAKEFILE b/v4.0/src/CMD/SORT/MAKEFILE
new file mode 100644
index 0000000..d64b66b
--- /dev/null
+++ b/v4.0/src/CMD/SORT/MAKEFILE
@@ -0,0 +1,36 @@
1#************************** makefile for cmd\... ***************************
2
3msg =..\..\messages
4dos =..\..\dos
5inc =..\..\inc
6hinc =..\..\h
7
8#
9####################### dependencies begin here. #########################
10#
11
12all: sort.exe
13
14sort.ctl: sort.skl \
15 $(msg)\$(COUNTRY).msg \
16 makefile
17
18sort.obj: sort.asm \
19 makefile \
20 sort.ctl \
21 sort.cla \
22 sort.cl1 \
23 sort.cl2 \
24 $(inc)\parse.asm \
25 $(inc)\psdata.inc \
26 $(inc)\syscall.inc \
27 $(inc)\msgserv.asm \
28 $(inc)\sysmsg.inc
29
30sortmes.obj: sort.asm \
31 makefile \
32 $(inc)\syscall.inc
33
34sort.exe: sort.obj sortmes.obj
35 link sort+sortmes,sort.exe;
36 exefix sort.exe 1 1
diff --git a/v4.0/src/CMD/SORT/SORT.ASM b/v4.0/src/CMD/SORT/SORT.ASM
new file mode 100644
index 0000000..0a60eb8
--- /dev/null
+++ b/v4.0/src/CMD/SORT/SORT.ASM
@@ -0,0 +1,1000 @@
1TITLE SORT FILTER FOR DOS
2 PAGE ,132 ;
3;**********************************************************
4;*
5;* UTILITY NAME: sort
6;*
7;* SOURCE FILE NAME: sort.asm
8;*
9;* UTILITY FUNCTION:
10;*
11;* External non-resident utility, written in Assembler.
12;* Reads from the standard input device until end-of-file,
13;* sorts the data (up to 64k) and writes the results to
14;* the standard output device. Input and output can be
15;* redirected.
16;*
17;* INPUT (Command line)
18;*
19;* SORT [/R] [/+ n]
20;*
21;* /R - Sort in reverse order
22;* /+n - Start sorting in column "n" , default 1
23;*
24;* OUTPUT:
25;* Sorted data will be written to the standard output device.
26;*
27;* ERROR CONDITIONS:
28;* Incorrect DOS version
29;* Insufficient disk space on target
30;* Insufficient memory to allocate SORT buffer
31;* Invalid parameter
32;*
33;* INTERNAL REFERENCES:
34;* Main
35;*
36;* SOURCE HISTORY:
37;* Modification History:
38;* 3-18-83 MZ (Microsoft)
39;* Fix CR-LF at end of buffer
40;* Fix small file sorting
41;* Fix CR-LF line termination bug
42;* Comment the Damn source
43;*
44;* 6-23-86 RW (IBM)
45;* Add DOS 3.30 support for multiple languages
46;* Inclusion of common DOS VERSION check equate
47;*
48;* ;AN000; Code added in DOS 4.0
49;* 5-19-87 RW (IBM) (DOS 4.0)
50;* Addition of IBM Parser Service Routines
51;* Addition of DOS Message Retriever Service Routines
52;* Add code page file tag support
53;*
54;* ;AN001; Code added in DOS 4.0
55;* ;AN002; DCR 191
56;* 9-18-87 BL (IBM) (DOS 4.0)
57;* Added Extended Attribute support for code page checking
58;* and file type checking.
59;* ;AN003; PTM 1805
60;* 10-19-87 BL (IBM) (DOS 4.0)
61;*
62;* ;AN004; PTM
63;* 01-29-87 BL (IBM) (DOS 4.0)
64;* Ran tool INSPECT on .lst file for optimizations
65;**********************************************************
66
67 PAGE ;
68;-------------------------
69;--- Macro definitions
70;-------------------------
71BREAK MACRO subtitle
72 SUBTTL subtitle
73 PAGE
74ENDM
75
76
77
78sys MACRO name ;system call macro
79 MOV AH,name
80 INT 21h
81 ENDM
82
83
84
85save MACRO reglist ;push those registers
86IRP reg,<reglist>
87 PUSH reg
88ENDM
89ENDM
90
91
92
93restore MACRO reglist ;pop those registers
94IRP reg,<reglist>
95 POP reg
96ENDM
97ENDM
98
99
100 PAGE ;
101;-------------------------------
102;--- Equates
103;-------------------------------
104FALSE EQU 0
105TRUE EQU NOT FALSE
106MAXREC EQU 256 ;MAXIMUM NUL RECORD SIZE
107
108SPACE EQU 0 ;Offset zero in the allocated block
109BUFFER EQU MAXREC ;Offset MAXREC in the allocated block
110
111RETCODE_NOERROR equ 0 ;AN000; DOS return code (errorlevel)
112RETCODE_ERROR equ 1 ;AN000; DOS return code (errorlevel)
113
114NO_CODEPAGE equ 0 ;AN000; Tag for files with no codepage
115
116GetCPSW equ 3303h ;AN000; Int 021h function calls
117GetExtAttr equ 5702h ;AN000;
118SetExtAttr equ 5704h ;AN000;
119;-----------------------
120;-- Parser equates
121;-----------------------
122EOL EQU -1 ;AN000; Indicator for End-Of-Line
123NOERROR EQU 0 ;AN000; Return Indicator for No Errors
124
125FarSW equ 0 ;AN000;
126DateSW equ 0 ;AN000;
127TimeSW equ 0 ;AN000;
128FileSW equ 0 ;AN000;
129CAPSW equ 0 ;AN000;
130CmpxSW equ 0 ;AN000;
131NumSW equ 1 ;AN000;
132KeySW equ 0 ;AN000;
133SwSW equ 1 ;AN000;
134Val1SW equ 1 ;AN000;
135Val2SW equ 0 ;AN000;
136Val3SW equ 0 ;AN000;
137DrvSW equ 0 ;AN000;
138QusSW equ 0 ;AN000;
139
140;-----------------------
141;-- Message equates
142;-----------------------
143STDIN equ 0
144STDOUT equ 1
145STDERR equ 2
146
147Msg_NoMem equ 2 ;AC003;
148Msg_NoDisk equ 4 ;AC003;
149Msg_sort equ 5 ;AN003;
150Msg_switch equ 3 ;AN003;
151
152;------------------------------
153; EXTENDED ATTRIBUTE Equates
154;------------------------------
155EAISBINARY equ 02h ;AN001; ea_type
156EASYSTEM equ 8000h ;AN001; ea_flags
157
158 PAGE ;
159;---------------------;
160.xlist ;
161.xcref ;
162INCLUDE syscall.inc ;
163INCLUDE sysmsg.inc ; ;AN000; Include message equates and MACROS
164.cref ;
165.list ;
166;---------------------;
167
168MSG_UTILNAME <SORT> ;AN000;
169
170SUBTTL Segments used in load order
171
172
173CODE SEGMENT
174CODE ENDS
175
176CONST SEGMENT PUBLIC BYTE
177CONST ENDS
178
179
180;-----------------------
181;--- Stack Segment
182;-----------------------
183CSTACK SEGMENT STACK
184 db 128 DUP (0) ;initial stack to be clear
185
186CSTACK ENDS
187
188
189
190;-------------------------------
191;--- Group
192;-------------------------------
193DG GROUP CODE,CONST,CSTACK
194
195
196;-------------------------------
197;--- Code Segment
198;-------------------------------
199CODE SEGMENT
200ASSUME CS:DG,DS:DG,ES:NOTHING,SS:CSTACK
201
202;-------------------------------
203;--- Data Definition
204;-------------------------------
205COLUMN dw 0 ;COLUMN TO USE FOR KEY + 1
206cp_reset db FALSE ;AN000;Flag indicating if Code Page was reset on target file
207
208;------------------------------------------DOS 3.30 - Russ Whitehead
209CTRY_INFO db ?
210CTRY_TABLE_OFF dw ?
211CTRY_TABLE_SEG dw ?
212;------------------------------------------
213
214MSG_SERVICES <MSGDATA> ;AN000;
215ASSUME ds:nothing
216
217;----------------------------------------
218;- STRUCTURE TO QUERY EXTENDED ATTRIBUTES
219;----------------------------------------
220querylist struc ;AN001; ;query general list
221qea_num dw 1 ;AN001;
222qea_type db EAISBINARY ;AN001;
223qea_flags dw EASYSTEM ;AN001;
224qea_namelen db ? ;AN001;
225qea_name db " " ;AN001;
226querylist ends ;AN001;
227
228cp_qlist querylist <1,EAISBINARY,EASYSTEM,2,"CP"> ;AN001; ;query code page attr.
229
230cp_list label word ;AN001; ;code page attr. get/set list
231 dw 1 ;AN001; ; # of list entries
232 db EAISBINARY ;AN001; ; ea type
233 dw EASYSTEM ;AN001; ; ea flags
234 db ? ;AN001; ; ea return code
235 db 2 ;AN001; ; ea name length
236 dw 2 ;AN001; ; ea value length
237 db "CP" ;AN001; ; ea name
238cp dw ? ;AN001; ; ea value (code page)
239cp_len equ ($ - cp_list) ;AN001;
240
241;-------Save area for Code Pages
242src_cp dw ? ;AN000; Save area for current code page
243tgt_cp dw ? ;AN000; Save area for current code page
244endlist label word ;AN000;
245
246 PAGE ;
247;******************************************************************************
248;* PARSER DATA STRUCTURES FOLLOW
249;******************************************************************************
250
251;------------------------------
252;- STRUCTURE TO DEFINE ADDITIONAL COMMAND LINE DELIMITERS
253;------------------------------
254parms label word ;AN000;
255 dw parmsx ;AN000; POINTER TO PARMS STRUCTURE
256 db 1 ;AN000; DELIMITER LIST FOLLOWS
257 db 1 ;AN000; NUMBER OF ADDITIONAL DELIMITERS
258 db ";" ;AN000; ADDITIONAL DELIMITER
259
260;------------------------------
261;- STRUCTURE TO DEFINE SORT SYNTAX REQUIREMENTS
262;------------------------------
263parmsx label word ;AN000;
264 db 0,0 ;AN000; THERE ARE NO POSITIONAL PARAMETERS
265 db 2 ;AN000; THERE ARE 2 SWITCHES (/R AND /+n)
266 dw sw1 ;AN000; POINTER TO FIRST SWITCH DEFINITION AREA
267 dw sw2 ;AN000; POINTER TO SECOND SWITCH DEFINITION AREA
268 dw 0 ;AN000; THERE ARE NO KEYWORDS IN SORT SYNTAX
269
270;------------------------------
271;- STRUCTURE TO DEFINE THE /R SWITCH
272;------------------------------
273sw1 label word ;AN000;
274 dw 0 ;AN000; NO MATCH FLAGS
275 dw 0 ;AN000; NO FUNCTION FLAGS
276 dw switchbuff ;AN000; PLACE RESULT IN switchbufF
277 dw novals ;AN000; NO VALUE LIST
278 db 1 ;AN000; ONLY ONE SWITCH IN FOLLOWING LIST
279rev_sw db "/R",0 ;AN000; /R INDICATES REVERSE SORT
280
281;------------------------------
282;- STRUCTURE TO DEFINE THE /+n SWITCH
283;------------------------------
284NUMERIC equ 08000h ;AN000; Control flag for numeric value
285NO_COLON equ 0020h ;AN000;
286
287sw2 label word ;AN000;
288 dw NUMERIC ;AN000; MATCH_FLAGS
289 dw NO_COLON ;AN000; NO FUNCTION FLAGS
290 dw switchbuff ;AN000; PLACE RESULT IN switchbufF
291 dw valuelist ;AN000; NEED VALUE LIST FOR n
292 db 1 ;AN000; ONLY 1 SWITCH ON FOLLOWING LIST
293col_sw db "/+",0 ;AN000; /+n INDICATES BEGIN SORT IN COLUMN n
294
295;------------------------------
296;- VALUE LIST DEFINITION FOR NO VALUES
297;------------------------------
298novals label word ;AN000;
299 DB 0 ;AN000; VALUE LIST
300
301;------------------------------
302;- VALUE LIST DEFINITION FOR /+n
303;------------------------------
304valuelist label word ;AN000;
305 db 1 ;AN000; ONE VALUE ALLOWED
306 db 1 ;AN000; ONLY ONE RANGE
307 db 1 ;AN000; IDENTIFY THE RANGE
308 dd 1,65535 ;AN000; USER CAN SPECIFY /+1 THROUGH /+65535
309
310;------------------------------
311;- RETURN BUFFER FOR SWITCH INFORMATION
312;------------------------------
313switchbuff label word ;AN000;
314sb_type db ? ;AN000; TYPE RETURNED
315sb_item_tag db ? ;AN000; SPACE FOR ITEM TAG
316sb_synonym dw ? ;AN000; ES:sb_synonym points to synonym
317
318sb_value dw ? ;AN000; SPACE FOR VALUE
319sb_value_extra dw ? ;AN000; UNUSED SPACE FOR VALUE
320
321 PAGE ;
322;**************************************************************
323;*
324;* SUBROUTINE NAME: main
325;*
326;* SUBROUTINE FUNCTION:
327;* Mainline routine, performs SYSLODMSG, calls routines to
328;* parse command line, performs the SORT and writes the
329;* results.
330;*
331;* INPUT:
332;* Command Line.
333;*
334;* File to be sorted will be read from Standard Input
335;* device handle 0.
336;*
337;* OUTPUT:
338;* Sorted data will be written to the Standard Output
339;* device handle 1.
340;*
341;* NORMAL EXIT:
342;* SORT will normally exit when data was successfully read
343;* in up to 64k or EOF, sorted, and displayed to the
344;* standard output device.
345;*
346;* ERROR EXIT:
347;* If any of the following errors, SORT will display the
348;* corresponding error message and terminate.
349;*
350;* Insufficient disk space on target device
351;* Incorrect DOS version
352;* Insufficient memory to sort
353;*
354;************************************************************
355
356;-------------------------
357; Preload messages
358;-------------------------
359 MSG_SERVICES <SORT.ctl,SORT.cla,SORT.cl1,SORT.cl2> ;AN000;
360 MSG_SERVICES <DISPLAYmsg,LOADmsg,CHARmsg,NOCHECKSTDIN> ;AN002; Make retriever services available
361
362 mov ax,cs ;AN003; ;load ES to the right area,
363 mov es,ax ;AN003;
364 mov ds,ax ;AN003;
365SORT:
366 call sysloadmsg ;AN000; Preload messages, Check DOS Version.
367 ;If Inc DOS Ver or error loading messages,
368 ;SYSLOADMSG will show msg and terminate for us
369 jnc parser ;AN000; If no error, parse command line
370 call sysdispmsg ;AN000; There was error. Let SYSDISPMSG Display
371 cmp bx,-1 ;AN000; Is this DOS 1.0 or 1.1 ?
372 je OLD_ABORT ;AN000; Yes, terminate old way
373
374 mov ah,Exit ;AN000; No, terminate new way
375 mov al,0 ;AN000; Errorlevel 0 (Compatible!)
376 int 021h ;AN000; Bye bye!
377
378OLD_ABORT: ;AN000; CS should point to PSP
379 mov ah,Abort ;AN000; Terminate program (AH=0)
380 int 021h ;AN000; Bye bye!
381;-----------------------------------
382;- DOS version is ok. Parse cmd line
383;-----------------------------------
384PARSER: ;AN000; message and terminate
385 call parse ;AN000; Parse command line
386
387;-----------------------------------
388; set up column for proper sort offset
389;-----------------------------------
390
391 ADD COLUMN,2
392 CMP COLUMN,2
393 JZ GOT_COL
394 DEC COLUMN
395
396;------------------------------------
397; Get sorting area, no more than 64K
398;------------------------------------
399GOT_COL:
400 MOV BX,1000H ;64K worth of paragraphs
401GET_MEM:
402 mov bp,bx ;AN003; save buffer length
403 sys ALLOC ;allocate them from somewhere
404 JNC GOT_MEM ;if error, BX has amount free, try to get it
405 OR BX,BX ;but, is BX = 0?
406 JNZ GET_MEM ;nope, try to allocate it
407 JMP short SIZERR ;AN004; ;complain
408
409GOT_MEM:
410;------------------------------------RussW:--Following add in DOS 3.3 for Nat Lang Support
411 push ax ;Save AX
412 push ds ;Save DS
413 push es ;Save ES
414 mov al,6 ;Function for Get collating sequence
415 mov bx,-1 ;Get active code page
416 mov dx,-1 ;Get info from active country
417 mov cx,5 ;Number of bytes to be returned
418 push cs ;Place code segment
419 pop es ;in ES
420 mov di,offset ctry_info ;Return area for 5 byte requested information
421 sys GetExtCntry ;Get extended country information
422 ;Ok, now copy the table in DOS to our segment
423 lds si,dword ptr cs:ctry_table_off
424 mov di,seg dg
425 mov es,di
426 mov di,offset dg:table
427 mov cx,word ptr [si]
428 add si,2
429 mov ax,256
430 sub ax,cx
431 add di,ax
432 cld
433 rep movsb
434 ;Done copying, so restore regs and cont
435 pop es ;Restore ES
436 pop ds ;Restore DS
437 pop ax ;Restore AX
438;------------------------------------RussW:--End 3.3 addition
439 MOV DS,AX ;Point DS to buffer
440 MOV ES,AX ;and point ES to buffer
441 MOV CL,4 ;2^4 bytes per paragraph
442 MOV BX,BP ;AN003; restore buffer length
443 SHL BX,CL ;Find out how many bytes we have
444 MOV BP,BX ;AN003; save buffer length in bytes
445
446;---------------------------
447; Clear out temporary record area
448;---------------------------
449 MOV CX,MAXREC/2 ;Size of temporary buffer (words)
450 MOV AX,' ' ;Character to fill with
451 XOR DI,DI ;AN004; ;Beginning of temp buffer
452 REP STOSW ;Blam.
453;-----------------------------------
454; Make sure source and target code pages are the same
455;-----------------------------------
456 call match_codepages ;AN000; Make sure codepages are the same
457;---------------------------
458; read in file from standard input
459;---------------------------
460 MOV DX,BUFFER + 2 ;DX = place to begin reading
461 MOV CX,BP ;AN003; ;CX is the max number to read
462 SUB CX,MAXREC + 2 ;remember offset of temp buffer
463SORTL:
464 XOR BX,BX ;Standard input
465 sys READ ;Read it in
466 ADD DX,AX ;Bump pointer by count read
467 SUB CX,AX ;subtract from remaining the count read
468 JZ SIZERR ;if buffer is full then error
469 OR AX,AX ;no chars read -> end of file
470 JNZ SORTL ;there were chars read. go read again
471 JMP SHORT SIZOK ;trim last ^Z terminated record
472SIZERR:
473 mov ax,msg_NoMem ;AN000; not enough memory error
474 mov dh,-1 ;AN003; class: utility error
475 call error_exit ;AN000; and write it out
476
477;---------------------------
478; Look for a ^Z. Terminate buffer at 1st ^Z.
479;---------------------------
480SIZOK:
481 MOV BX,DX ;save end pointer
482 MOV CX,DX ;get pointer to end of text
483 SUB CX,BUFFER+2 ;dif in pointers is count
484 MOV AL,1AH ;char is ^Z
485 MOV DI,BUFFER+2 ;point to beginning of text
486 REPNZ SCASB ;find one
487 JNZ NoBack ;nope, try to find CRLF
488 DEC BX ;pretend that we didn't see ^Z
489NoBack:
490 SUB BX,CX ;sub from endpointer the number left
491 SUB BX,2 ;Hope for a CR LF at end
492 CMP WORD PTR [BX],0A0Dh ;Was there one there?
493 JZ GOTEND ;yep, here is the end
494 ADD BX,2 ;nope, bump back to SCASB spot
495 CMP BYTE PTR [BX],AL ;Was there ^Z there?
496 JZ GOTEND ;yep, chop it
497 INC BX ;Nope, skip last char
498GOTEND:
499 MOV BP,BX ;BP = filesize-2(CRLF)+temp buffer+2
500 MOV WORD PTR DS:[BP],0 ;0 at end of the file
501
502;---------------------------
503; We now turn the entire buffer into a linked list of chains by
504; replacing CRLFs with the length of the following line (with 2 for CRLF)
505;---------------------------
506 MOV BX,BUFFER ;pointer to line head (length)
507 MOV DI,BUFFER+2 ;pointer to line text
508REPLACE_LOOP:
509 MOV AL,13 ;char to look for is CR
510 MOV CX,BP ;count = end pointer
511 SUB CX,DI ;chop off start point to get length
512 INC CX ;add 1???
513REPLACE_SCAN:
514 REPNZ SCASB ;look for CR
515 JNZ REPLACE_SKIP ;count exhausted
516 CMP BYTE PTR [DI],10 ;LF there?
517 JNZ REPLACE_SCAN ;nope, continue scanning
518REPLACE_SKIP:
519 MOV AX,DI ;AX to point after CR
520 DEC AX ;AX to point to CR
521 save <AX> ;save pointer
522 SUB AX,BX ;AX is length of line found
523 MOV [BX],AX ;stuff it in previous link
524 restore <BX> ;get pointer to next
525 INC DI ;skip LF???
526 JCXZ END_REPLACE_LOOP ;no more to scan -> go sort
527 JMP REPLACE_LOOP ;look for next
528
529END_REPLACE_LOOP:
530 MOV WORD PTR [BX],0 ;terminate file with nul
531 LEA BP,[BX+2] ;remember the null line at end
532 MOV DI,BUFFER ;DI is start of unsorted section
533
534;---------------------------
535; begin sort. Outer loop steps over all unsorted lines
536;---------------------------
537OUTER_SORT_LOOP:
538 MOV BX,DI ;BX is start of unsorted section
539 MOV SI,BX ;SI is scanning place link
540 CMP WORD PTR [BX],0 ;are we at the end of the buffer?
541 JNZ INNER_SORT_LOOP ;No, do inner process
542 JMP END_OUTER_SORT_LOOP ;yes, go dump out
543
544;---------------------------
545; BX points to best guy found so far. We scan through the sorted section
546; to find an appropriate insertion point
547;---------------------------
548INNER_SORT_LOOP:
549 ADD SI,[SI] ;link to next fellow
550 MOV AX,[SI] ;get length of comparison guy
551 OR AX,AX ;test for end of buffer
552 JZ END_INNER_SORT_LOOP ;if zero then figure out insertion
553 save <SI,DI> ;save SI,DI
554 MOV DI,BX ;DI = pointer to tester link
555 SUB AX,COLUMN ;adjust length for column
556 JA AXOK ;more chars in tester than column?
557 XOR SI,SI ;AN004; ;point SI to blank area
558 MOV AX,MAXREC ;make AX be max length
559AXOK:
560 MOV DX,[DI] ;get length of best guy
561 SUB DX,COLUMN ;adjust length for column
562 JA DXOK ;there are more chars after column
563 XOR DI,DI ;AN004; ;point air to a space
564 MOV DX,MAXREC ;really big record
565DXOK:
566 MOV CX,AX ;AX is shortest record
567 CMP AX,DX ;perhaps DX is shorter
568 JB SMALL ;nope, leace CX alone
569 MOV CX,DX ;DX is shorter, put length in CX
570SMALL:
571 ADD DI,COLUMN ;offset into record
572 ADD SI,COLUMN ;offset into other record
573 push bx
574 push ax
575 mov bx,offset dg:table
576tloop: lodsb
577 xlat byte ptr cs:[bx]
578 mov ah,al
579 mov al,es:[di]
580 inc di
581 xlat byte ptr cs:[bx]
582 cmp ah,al
583 loopz tloop
584 pop ax
585 pop bx
586 restore <DI,SI> ;get head pointers back
587 JNZ TESTED_NOT_EQUAL ;didn't exhaust counter, conditions set
588 CMP AX,DX ;check string lengths
589TESTED_NOT_EQUAL:
590
591;---------------------------
592; NOTE! jae is patched to a jbe if file is to be sorted in reverse!
593;---------------------------
594CODE_PATCH label byte
595 JAE INNER_SORT_LOOP ;if this one wasn't better then go again
596 MOV BX,SI ;it was better, save header
597 JMP INNER_SORT_LOOP ;and scan again
598
599END_INNER_SORT_LOOP:
600 MOV SI,BX ;SI is now the best person
601 CMP SI,DI ;check best for current
602 JZ END_INSERT ;best equals current, all done
603
604;---------------------------
605; SI points to best line found so far
606; DI points to a place to insert this line
607; DI is guaranteed to be < SI
608; make room for line at destination
609;---------------------------
610 MOV DX,[SI] ;get length of line
611 save <SI,DI> ;save positions of people
612 STD ;go right to left
613 MOV CX,BP ;get end of file pointer
614 SUB CX,DI ;get length from destination to end
615 MOV SI,BP ;start from end
616 DEC SI ;SI points to end of file
617 MOV DI,SI ;destination is end of file
618 ADD DI,DX ;DI points to new end of file
619 REP MOVSB ;blam. Move every one up
620 CLD ;back left to right
621 restore <DI,SI> ;get old source and destination
622;---------------------------
623; MOVE NEW LINE INTO PLACE
624;---------------------------
625 save <DI> ;save destination
626 ADD SI,DX ;adjust for previous movement
627 save <SI> ;save this value
628 MOV CX,DX ;get number to move
629 REP MOVSB ;blam. move the new line in
630 restore <SI,DI> ;get back destination and new source
631;---------------------------
632; DELETE LINE FROM OLD PLACE
633;---------------------------
634 save <DI> ;save destination
635 MOV CX,BP ;pointer to end
636 ADD CX,DX ;remember bump
637 SUB CX,SI ;get count of bytes to move
638 INC CX ;turn it into a word
639 SHR CX,1 ;or a count of words
640 MOV DI,SI ;new destination of move
641 ADD SI,DX ;offset of block
642 REP MOVSW ;blam, squeeze out the space
643 restore <DI> ;get back original destination
644 MOV WORD PTR DS:[BP-2],0 ;remake the end of file mark
645
646END_INSERT:
647 ADD DI,[DI] ;link to next guy
648 JMP OUTER_SORT_LOOP ;and continue
649;------------------------------
650; PUT BACK IN THE CR-LF
651;------------------------------
652END_OUTER_SORT_LOOP:
653 MOV DI,BUFFER ;start at beginning (where else)
654 MOV CX,[DI] ;count of butes
655
656INSERT_LOOP:
657 ADD DI,CX ;point to next length
658 MOV CX,[DI] ;get length
659 MOV WORD PTR [DI],0A0DH ;replace length with CRLF
660 AND CX,CX ;AN004; ;check for end of file
661 JNZ INSERT_LOOP ;nope, try again
662
663WRITE_FILE:
664 MOV DX,BUFFER+2 ;get starting point
665 MOV CX,BP ;pointer to end of buffer
666 SUB CX,DX ;dif in pointers is number of bytes
667 MOV BX,1 ;to standard output
668 sys WRITE ;write 'em out
669 JC BADWRT ;some bizarre error -> flag it
670 CMP AX,CX ;did we write what was expected?
671 JZ WRTOK ;yes, say bye bye
672BADWRT:
673
674;;;;; mov ax,msg_NoDisk ;AN000; Strange write error
675;;;;; mov dh,-1 ;AN003; class: extended error
676;;;;; call error_exit ;AN000; Bye bye
677 mov al,RETCODE_ERROR ;AN000; return an error code (errorlevel)
678 sys EXIT ;AN000;
679WRTOK:
680 MOV AL,RETCODE_NOERROR ;AN000; Errorlevel 0 (No error!)
681 sys EXIT ;bye!
682
683 PAGE ;
684;************************************************************
685;*
686;* SUBROUTINE NAME: display_msg
687;*
688;* SUBROUTINE FUNCTION:
689;* Display the requested message to the specified handle
690;*
691;* INPUT:
692;* 1) AX = Number of the message to be displayed.
693;* 2) BX = Handle to be written to.
694;*
695;* OUTPUT:
696;* The message corresponding to the requested msg number will
697;* be written to the requested handle. There is no substitution
698;* text in SORT.
699;*
700;* NORMAL EXIT:
701;* Message will be successfully written to requested handle.
702;*
703;* ERROR EXIT:
704;* None. Note that theoretically an error can be returned from
705;* SYSDISPMSG, but there is nothing that the application can do.
706;*
707;* INTERNAL REFERENCES:
708;* System Display Message service routines
709;*
710;* EXTERNAL REFERENCES:
711;* None
712;*
713;************************************************************
714
715display_msg proc near ;AN000;
716 push ds ;AN000; save DS value
717 push cs ;AN000; get DS addressability
718 pop ds ;AN000;
719
720 xor cx,cx ;AN004; ;AN000; No substitution text
721;; mov dh,-1 ;AN003; Message class
722 ; 1=DOS Extended error
723 ; 2=DOS Parse error
724 ; -1=Utility message
725 mov dl,0 ;AN000; DOS INT 21H function number to use for input
726 ; 00H=No input, 01H=Keyboard input,
727 ; 07H=Direct Console Input Without Echo,
728 ; 08H=Console Input Without Echo, 0AH=Buffered Keyboard Input
729 call SYSDISPMSG ;AN000;
730
731 pop ds ;AN000; restore DS
732 ret ;AN000;
733display_msg ENDP ;AN000;
734
735 PAGE ;
736;************************************************************
737;*
738;* SUBROUTINE NAME: parse
739;*
740;* SUBROUTINE FUNCTION:
741;* Call the DOS PARSE Service Routines to process the command
742;* line. Search for valid switches (/R and /+n) and take
743;* appropriate action for each. Display error message and
744;* terminate on error.
745;*
746;* INPUT: None
747;*
748;* OUTPUT: None
749;*
750;* NORMAL EXIT:
751;*
752;* If /R specified, then patches code to perform reverse sort
753;* by changing JAE to a JB.
754;*
755;* If /+n entered, COLUMN will be set to "n," otherwise COLUMN
756;* will be set to 1.
757;*
758;* ERROR EXIT:
759;*
760;* If user enters any parameter or switch other than /R or /+n,
761;* or an invalid value for "n", then this routine will display
762;* the "Invalid Parameter" error message and terminate with
763;* errorlevel 1.
764;*
765;* EXTERNAL REFERENCES:
766;* System parse service routines
767;* INT21 - GET PSP Function Call 062h
768;*
769;************************************************************
770
771parse proc near ;AN000;
772
773 sys GetCurrentPSP ;AN000; Get PSP address, returned in BX
774
775 mov ds,bx ;AN000; Put PSP Seg in DS
776 mov si,081h ;AN000; Offset of command line in PSP
777 cmp byte ptr ds:080h,0 ;AN000; Check length of command line
778 je end_parse ;AN000; If 0 len, the we are done parsing
779 xor cx,cx ;AN000; Number of parms processed so far = 0
780 push cs ;AN000; Put CS
781 pop es ;AN000; in ES
782;---------------------------------
783;- Loop for each operand at DS:SI (Initially PSP + 081h)
784;---------------------------------
785parse_loop: ;AN000;
786 mov di,offset parms ;AN000; Address of parse control block
787 xor dx,dx ;AN000; Reserved
788 call sysparse ;AN000; Parse parm at DS:SI
789 cmp ax,EOL ;AN000; Q: Are we at end of command line?
790 je end_parse ;AN000; YES: We are done
791 and ax,ax ;AN004; ;AN000; NO: Q: Any errors?
792 jne parse_error ;AN000; YES: Display msg and terminate
793 mov bx,sb_synonym ;AN000; Get offset of switch entered
794;----------------------------------
795;- If user said /R, then patch code
796;----------------------------------
797 cmp bx,offset rev_sw ;AN000; If user specified /R
798 jne check_column ;AN000;
799 mov cs:code_patch,072h ;AN000; Sleazy patch to make reverse order sort
800 jmp parse_loop ;AN000; Look for another parm
801
802;---------------------------------------------
803;- If user said /+n, then save COLUMN index
804;---------------------------------------------
805check_column: ;AN000;
806 cmp bx,offset col_sw ;AN000; Q: Did user specified /+n ?
807 jne switch_error ;AC003; No: Unrecognized parm
808 mov ax,sb_value ;AN000; Yes: Get number entered by user
809 mov column,ax ;AN000; Set up column to begin sort
810 jmp parse_loop ;AN000; Check for next parm
811
812;------------------------------------------------------------
813;- If any other parameter specified, display message and die
814;------------------------------------------------------------
815switch_error: ;AN003;
816 mov ax,Msg_switch ;AN003;
817parse_error: ;AN000;
818 mov dh,2 ;AN003; class: parse error
819 call error_exit ;AN000; Terminate utility
820
821end_parse: ;AN000;
822 ret ;AN000;
823parse endp ;AN000;
824
825 PAGE ;
826;************************************************************
827;*
828;* SUBROUTINE NAME: error_exit
829;*
830;* SUBROUTINE FUNCTION:
831;* Displays the message number in AX to the standard
832;* error device, then terminates with errorlevel 1.
833;*
834;* INPUT: AX = Message number
835;*
836;* INTERNAL REFERENCES:
837;* display_msg
838;*
839;* EXTERNAL REFERENCES:
840;* INT 021h - Terminate Function 043h
841;*
842;************************************************************
843error_exit proc near ;AN000;
844 call prt_sort ;AN003;
845 mov bx,STDERR ;AN000; output to standard error
846 xor cx,cx ;AN004; ;AN003;
847 call display_msg ;AN000; and write it out
848 mov al,RETCODE_ERROR ;AN000; return an error code (errorlevel)
849 sys EXIT ;AN000;
850 ret ;AN000; Meaningless RET
851error_exit endp ;AN000;
852
853
854;************************************************************
855;*
856;* SUBROUTINE NAME: match_codepages
857;*
858;* SUBROUTINE FUNCTION:
859;* Check to see if Code Page Support is active. If so,
860;* check code page of input and output handles. If the
861;* source file has a code page file tag AND the target
862;* handles code page is different, then set code page
863;* of the target to that of the source.
864;*
865;* INTERNAL REFERENCES:
866;* none
867;*
868;* EXTERNAL REFERENCES:
869;* INT 021h - Check CPSW
870;* INT 021h - Get Extended Attributes by Handle
871;* INT 021h - Set Extended Attributes by Handle
872;*
873;************************************************************
874
875match_codepages proc near ;AN000;
876
877;-----------------------------------
878; Check status of Code page support
879;-----------------------------------
880 push es ;AN000; Save ES register
881 push ds ;AN001; Save DS register
882;
883 mov ax,cs ;AN001; ES, DS -> CS
884 mov ds,ax ;AN001;
885 mov es,ax ;AN001;
886;
887 mov ax,GetCPSW ;AN000; Get CPSW state, assume support is OFF
888 int 021h ;AN000; DL: 0=NotSupported,1=Supported
889 cmp dl,1 ;AN000; CPSW supported if DL=1
890 jne done_cpsw ;AN000; If not supported, we're done
891;-----------------------------------
892; Get Code Pages of STDIN and STDOUT
893;-----------------------------------
894 mov ax,GetExtAttr ;AN000; Get Extended Attributes by Handle
895 mov bx,STDOUT ;AN000; For Standard output device
896 mov di,offset cp_list ;AC001; Return buffer address
897 mov si,offset cp_qlist ;AN001; Query the code page attribute
898 mov cx,cp_len ;AN001; return buffer length
899 int 021h ;AN000;
900 jc done_cpsw ;AN000; Error condition, let system handle
901 mov ax,cp ;AN000; Save target code page
902 mov tgt_cp,ax ;AN000; for later reference
903
904 mov ax,GetExtAttr ;AN000; Get Extended Attributes by Handle
905 xor bx,bx ;AN004; ;AN000; bx = STDIN (0) For Standard input device
906 mov di,offset cp_list ;AC001; Return buffer address
907 mov si,offset cp_qlist ;AN001; Query the code page attribute
908 mov cx,cp_len ;AN001; return buffer length
909 int 021h ;AN000;
910 jc done_cpsw ;AN000; Error condition, let system handle
911 mov ax,cp ;AN000; Save source code page
912 mov src_cp,ax ;AN000; for later reference
913
914 mov ax,src_cp ;AN000; Get source codepage
915 and ax,ax ;AN004; ;AN000; IF no codepage
916 je done_cpsw ;AN000; THEN no action required;
917 cmp ax,tgt_cp ;AN000; IF src_cp = tgt_cp
918 je done_cpsw ;AN000; THEN no action required;
919;-------------------------------------
920;- Set CP of target to that of source
921;-------------------------------------
922 mov cp_reset,TRUE ;AN000; Set flag indicating change
923 mov ax,SetExtAttr ;AN000; Set Extended Attributes by Handle
924 mov bx,STDOUT ;AN000; For Standard output device
925 mov di,offset cp_list ;AC001; Input buffer address
926 int 021h ;AN000;
927
928done_cpsw: ;AN000;
929 pop ds ;AN001; Restore DS register
930 pop es ;AN000; Restore ES register
931 ret ;AN000;
932match_codepages endp ;AN000;
933
934 PAGE ;
935;************************************************************
936;*
937;* SUBROUTINE NAME: prt_sort
938;*
939;* SUBROUTINE FUNCTION:
940;* Preceeds all error messages with "SORT: ".
941;*
942;* INTERNAL REFERENCES:
943;* none
944;* EXTERNAL REFERENCES:
945;* none
946;************************************************************
947prt_sort proc near ;AN003;
948 push ax ;AN003;
949 push dx ;AN003;
950;
951 mov dh,-1 ;AN003;
952 mov ax,Msg_sort ;AN003;
953 xor cx,cx ;AN004; ;AN003;
954 mov bx,STDERR ;AN003;
955 call display_msg ;AN003;
956;
957 pop dx ;AN003;
958 pop ax ;AN003;
959;
960 ret ;AN003;
961prt_sort endp ;AN003;
962
963
964 PAGE ;
965;--------------------
966.xlist
967.xcref
968INCLUDE parse.asm
969include msgdcl.inc
970.cref
971.list
972;--------------------
973
974CODE ENDS
975
976
977
978
979
980
981
982CONST SEGMENT PUBLIC BYTE
983
984 extrn table:byte
985
986CONST ENDS
987
988
989
990
991SUBTTL Initialized Data
992;-------------------------------
993;--- Stack Segment
994;-------------------------------
995CSTACK SEGMENT STACK
996 db (362 - 80h) + 96 dup (0) ;(362 - 80h) == New - Old IBM
997 ;interrupt reqs. == size of growth
998CSTACK ENDS
999
1000 END SORT
diff --git a/v4.0/src/CMD/SORT/SORT.LNK b/v4.0/src/CMD/SORT/SORT.LNK
new file mode 100644
index 0000000..6ad8920
--- /dev/null
+++ b/v4.0/src/CMD/SORT/SORT.LNK
@@ -0,0 +1,4 @@
1SORT+
2SORTMES
3SORT.EXE;
4 \ No newline at end of file
diff --git a/v4.0/src/CMD/SORT/SORT.SKL b/v4.0/src/CMD/SORT/SORT.SKL
new file mode 100644
index 0000000..b7a695f
--- /dev/null
+++ b/v4.0/src/CMD/SORT/SORT.SKL
@@ -0,0 +1,12 @@
1:util SORT ;AN000;
2:class 1 ;AN000;
3
4:class 2 ;Parser errors ;AN003;
5
6:class A ;AN000;
7:use 1 COMMON1 ;AN000; ;"Incorrect DOS version",CR,LF
8:use 2 EXTEND8 ;AN000; ;"Insufficient memory",CR,LF
9:use 4 COMMON20 ;AN003;
10:def 5 "SORT: " ;AN003;
11
12:end ;AN000;
diff --git a/v4.0/src/CMD/SORT/SORTMES.ASM b/v4.0/src/CMD/SORT/SORTMES.ASM
new file mode 100644
index 0000000..24761e4
--- /dev/null
+++ b/v4.0/src/CMD/SORT/SORTMES.ASM
@@ -0,0 +1,85 @@
1TITLE SORT Messages
2
3false equ 0
4true equ not false
5msver equ false
6ibm equ true
7internat equ true
8
9msg Macro lbl,msg
10local a
11public lbl,lbl&len
12lbl&len dw a - lbl
13lbl db msg
14a label byte
15endm
16
17CONST SEGMENT PUBLIC BYTE
18
19if internat
20 public table
21;This table defibes the coalating sequence to be used for
22;international characters. This table also equates
23;lower case character to upper case unlike a straight ASCII sort.
24;If your character set is like the IBM PC simply turn
25;on the IBM conditional. If it is different simply modify the
26;table appropriately. Note: to insert a foreign language character
27;between two ASCII characters it will be necessary to
28;"shift" all the ASCII characters to make room for a new character.
29;If this is done be sure to equate the foreign characters to the new
30;values instead of the old values which have been set here to the
31;upper case ASCII values.
32
33table db 0,1,2,3,4,5,6,7
34 db 8,9,10,11,12,13,14,15
35 db 16,17,18,19,20,21,22,23
36 db 24,25,26,27,28,29,30,31
37 db " ","!",'"',"#","$","%","&","'"
38 db "(",")","*","+",",","-",".","/"
39 db "0","1","2","3","4","5","6","7"
40 db "8","9",":",";","<","=",">","?"
41 db "@","A","B","C","D","E","F","G"
42 db "H","I","J","K","L","M","N","O"
43 db "P","Q","R","S","T","U","V","W"
44 db "X","Y","Z","[","\","]","^","_"
45 db "`","A","B","C","D","E","F","G"
46 db "H","I","J","K","L","M","N","O"
47 db "P","Q","R","S","T","U","V","W"
48 db "X","Y","Z","{","|","}","~",127
49if msver
50 db 128,129,130,131,132,133,134,135
51 db 136,137,138,139,140,141,142,143
52 db 144,145,146,147,148,149,150,151
53 db 152,153,154,155,156,157,158,159
54 db 160,161,162,163,164,165,166,167
55 db 168,169,170,171,172,173,174,175
56 endif
57if ibm
58 db "C","U","E","A","A","A","A","C"
59 db "E","E","E","I","I","I","A","A"
60 db "E","A","A","O","O","O","U","U"
61 db "Y","O","U","$","$","$","$","$"
62 db "A","I","O","U","N","N",166,167
63 db "?",169,170,171,172,"!",'"','"'
64 endif
65 db 176,177,178,179,180,181,182,183
66 db 184,185,186,187,188,189,190,191
67 db 192,193,194,195,196,197,198,199
68 db 200,201,202,203,204,205,206,207
69 db 208,209,210,211,212,213,214,215
70 db 216,217,218,219,220,221,222,223
71if ibm
72 db 224,"S"
73endif
74if msver
75 db 224,225
76endif
77 db 226,227,228,229,230,231
78 db 232,233,234,235,236,237,238,239
79 db 240,241,242,243,244,245,246,247
80 db 248,249,250,251,252,253,254,255
81 endif
82
83CONST ENDS
84 END
85 \ No newline at end of file