home *** CD-ROM | disk | FTP | other *** search
- ;===================================================
- ; PROGRAM LC Version 1.0 by Dave Whitman
- ;
- ; Filter to convert a file to all lower case.
- ; Non-alphabetic characters are not affected.
- ;
- ; Syntax: LC [?] [/u] [<infile] [>outfile]
- ;
- ; The ? option prints a help message.
- ; /U modifys the conversion to give all caps.
- ;
- ; Requires DOS 2.0, will abort under earlier versions.
- ;====================================================
-
- ;============
- ; Equates
- ;============
-
- @read equ 3FH ;read file/device
- @write equ 40H ;write file/device
- @dosver equ 30H ;get dos version
- @prnstr equ 09H ;print string
-
- cr equ 0DH ;carriage return character
- lf equ 0AH ;line feed character
-
- stdin equ 0000H ;standard input
- stdout equ 0001H ;standard output
- u equ 01H ;upper case option selected
-
- buf_size equ 512 ;size of input and output buffers
-
- param_count equ [80H]
- param_area equ [81H]
- mem_avail equ [06H] ;PSP field: memory available in segment
-
- up_mask equ 11011111B ;mask for lowercase conversion (with AND)
- low_mask equ 00100000B ;mask for uppercase conversion (with OR)
-
- main proc far
- call setup ;check dos, parse options
- call process ;count w, l, c from std i/o
- int 20H ;and return to dos
- endp
-
- ;======================================
- ; SUBROUTINE SETUP
- ; Checks for proper DOS, parses options
- ;======================================
- setup proc near
-
- mov ah, @dosver ;what dos are we under?
- int 21H
- cmp al, 2 ;2.0 or over?
- jae a_mem ;yes, skip
-
- mov ah, @prnstr ;no, bitch
- mov dx, offset(baddos)
- int 21H
- pop ax ;reset stack
- int 20H ;and exit
-
- a_mem mov ax, mem_avail ;do we have room for the buffers?
- cmp ax, buf_size*2
- jae a_help ;yes
- mov ah, @prnstr ;no, bitch
- mov dx, offset(nomem)
- int 21H
- pop ax ;reset stack
- int 20H ;and exit
-
- a_help xor ch,ch ;cx <== param count
- mov cl, param_count ; "
- cmp cl, 00H ;any params?
- je aexit ;return if none
-
- mov di, offset(param_area) ;scan for help request
- mov al, '?'
- repnz ;repeat until matched or end
- scasb
- jnz a_par ;reached end, no match? skip
- mov ah, @prnstr ;found ?, so print help
- mov dx, offset(help)
- int 21H
- pop ax ;pop stack
- int 20H ;and exit
-
- a_par xor ch, ch ;cx <== param count
- mov cl, param_count ; "
- mov di, offset(param_area) ;scan for options
- a_loop mov al, '/' ;will be marked with /
- repnz ;repeat until matched or end
- scasb
- jnz aexit ;reached end, no match? skip
-
- mov al, [di] ;get option char (right after '/')
- and al, up_mask ;guarantees upper case for compare
-
- cmp al, 'U' ;option U specified?
- jne a_pend ;nope
- orb options, u ;yes, set flag
- a_pend jmps a_loop ;and loop
-
- aexit ret
-
- baddos db cr lf 'This program requires DOS 2.0!' cr, lf, '$'
-
- nomem db cr lf 'Insufficient memory, program aborted' cr lf '$'
-
-
- help db cr lf
- db 'LC version 1.0' cr lf
- db cr lf
- db '1/2/86 by D. Whitman' cr lf
- db cr lf
- db 'Syntax: LC [?] [/u] [<infile] [>outfile]' cr lf
- db cr lf
- db 'Reads stdin and writes all lower case to stdout.' cr lf
- db cr lf
- db 'Options:' cr lf
- db ' ? = print this help message' cr lf
- db ' /u = upper case output' cr lf
- db cr lf
- db 'This program is in the public domain.' cr lf
- db cr lf '$'
- endp
-
- ;=========================================
- ; SUBROUTINE PROCESS
- ;
- ; 1. load input buffer
- ; 2. convert each char, pass to output buffer
- ; 3. dump output buffer
- ; 4. repeat until EOF
- ;==========================================
-
- process proc near
-
- bu1 mov ah, @read ;read
- mov bx, stdin ;from stdin
- mov cx, buf_size ;one buffer's worth
- mov dx, offset(buf_in)
- int 21H
- cmp ax, 00H ;test for EOF
- jz buexit ;if so, done
-
- push ax ;save number of chars read
- mov cx, ax ;cx <== number chars read
- mov si, offset(buf_in) ;source is input buffer
- mov di, offset(buf_out) ;destination is output buffer
-
- bu2 lodsb ;al <== next char from buffer
- cmp al, 'A' ;test if alphabetic char
- jb bu4 ;too low? skip
- cmp al, 'Z'
- jbe bu3 ;in range? is upper case, so process
- cmp al, 'a' ;how about a lower case char?
- jb bu4 ;nope
- cmp al, 'z' ;maybe, check upper bound
- ja bu4 ;nope (falls through if lower case)
-
- bu3 ;if here, al guaranteed alphabetic
- testb options, u ;was option u specified?
- jnz bu_up ;yes, jump and set upper case
- or al, low_mask ;no, convert to lower case
- jmps bu4 ; and skip u/c conversion
- bu_up and al, up_mask ;convert to upper case
- bu4 stosb ;put in output buffer
- loop bu2 ;loop until input buffer empty
-
- ;dump output buffer
- mov ah, @write ;write
- mov bx, stdout ;to stdout
- pop cx ;number of chars read
- mov dx, offset(buf_out)
- int 21H
-
- jmps bu1 ;and loop until EOF
-
- buexit ret
- endp
-
- ;=================
- ;GLOBAL VARIABLES
- ;=================
- options db 00H ;byte of option flags
-
- ;=====================================================
- ;BUFFERS
- ;
- ; No space is actually allocated for the buffers.
- ; At run time, the program checks to ensure there
- ; is suffcient free memory, then uses the memory
- ; immediately after itself for buffers.
- ;
- ; This stratagy minimizes the size of the object file,
- ; and lets the program load quicker.
- ;======================================================
-
- buf_in ;input buffer
-
- org offset($+buf_size) ;this is a trick to set the address
- ;the output buffer.
- ;the address of buf_out is set to be
- ;the offset of the input buffer, plus
- ;the buffer length.
-
- buf_out ;output buffer