home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 June
/
SIMTEL_0692.cdr
/
msdos
/
dirutl
/
newchdir.arc
/
C.ASM
next >
Wrap
Assembly Source File
|
1988-11-19
|
9KB
|
385 lines
page 60,132
; Copyright (C) 1988 Mark Adler Pasadena, CA
; All rights reserved.
title C -- enhanced change directory command
name C
comment #
C.COM -
This program is an enhanced change directory (CD) command. It is used
like CD, except that abbreviations of subdirectory names are accepted.
Only that part of each subdirectory name that uniquely distinguishes it
from the others is necessary. For example, suppose the current drive
has this directory tree:
\ ─┬─ DOS
├─ BIN ─┬─ TURBOC
│ ├─ MASM
│ └─ MATHCAD
└─ USR ─┬─ UTIL
└─ BBS ─┬─ COMPUSRV
└─ BULL
Then the command:
c \u\b\b
will make the current directory \USR\BBS\BULL. The command:
c \b\ma
will not change the directory, but instead give the response:
\BIN\ma*.* is ambiguous---it matches: MASM,MATHCAD
Then the command:
c \m\mat
will make the current directory \BIN\MATHCAD. Whether changing a
directory or not, C will display the current directory of the drive
specified (or the current drive if none is specified).
Putting this program on a RAM disk and setting the PATH appropriately
will make C as fast as resident commands (like CD).
#
;
; Program segment.
;
c segment
assume CS:c,DS:c,ES:c,SS:c
;
; Structure for BP data.
bpdata struc
find db 21 dup (?) ;Find first, next DTA.
fattr db ? ;Attribute of file found.
dw 4 dup (?) ;Time, date, size of file found.
fname db 13 dup (?) ;Name of file found
tname db 13 dup (?) ;Temporary save for name.
drv db ? ;Drive specified or current drive.
db ? ;(just to make it even)
bpdata ends
;
; Command line.
org 80h
cmd label byte
;
; Start of .COM code.
org 100h
start:
jmp cpyrt
db 13,'Enhanced chdir version 1.0 '
db 'Copyright (C) 1988 Mark Adler',13,10
db 'All rights reserved.',13,10
db 13,10
db 'Use this command like CD, except that you do not have to use the'
db 13,10
db 'whole name for each subdirectory. Only the part that uniquely'
db 13,10
db 'identifies it from the others is needed.'
db 13,10,'Z'-64
cpyrt:
;
; set up.
cld ;Assumed to hold throughout this program.
sub SP,size bpdata ;Allocate space for BP data.
mov BP,SP
lea DX,[BP].find ;Set DTA to the find area.
mov AH,1Ah
int 21h
; get current drive and total drives.
mov AH,19h
int 21h
mov DL,AL ;Save drive for select disk.
inc AX
mov [BP].drv,AL
mov AH,0Eh ;Set current drive to current drive, just to get
int 21h ; the total number of drives.
mov CL,AL ;Save total.
; set up command line, point SI to first non-blank.
mov SI,offset cmd
lodsb ;Get length and terminate line with a 0.
cbw
mov BX,AX
mov byte ptr [SI+BX],0
isb:
cmp byte ptr [SI],' '
jne nonb
inc SI
jmp short isb
nonb:
; see if anything on command line.
cmp byte ptr [SI],0
jne args
jmp showdir ;If not, go show the current directory.
args:
; initialize path, pointer to path.
mov DI,offset path
mov byte ptr [DI],0
; Pull out drive, if specified.
cmp byte ptr [SI+1],':'
jne nodrv
mov AL,[SI]
and AL,5Fh ;Convert lower to upper case.
sub AL,'A'-1
mov DX,offset err1
cmp AL,1 ;Check bounds.
jb erra
cmp AL,CL ;Must be less than or equal to total drives.
jbe dok
erra:
jmp errx
dok:
mov [BP].drv,AL
movsw ;Copy drive letter and colon to path.
nodrv:
; see if more than just a drive.
cmp byte ptr [SI],0
jne ismore
jmp showdir ;If not, just show directory.
ismore:
; for each part of specified path, find a match.
nxtlvl:
; pull off next part of path.
mov BX,DI ;Level pointer is now BX.
mov AH,0 ;Initialize dot count.
lodsb ;Get first character.
pullp:
cmp AL,'.' ;See if it's a dot.
jne nodot
inc AH ;If so, increment dot count.
nodot:
stosb ;Store character.
lodsb ;Get next character.
cmp AL,'\' ;See if path delimiter or end of string.
je pulend
cmp AL,'/'
je pulend
cmp AL,0
jne pullp ;If not, copy more.
pulend:
dec SI ;Point back to character that ended it.
; point level past delimiter, see if name there to match.
cmp byte ptr [BX],'\'
je skipdel
cmp byte ptr [BX],'/'
jne noskip
skipdel:
inc BX
cmp BX,DI ;See if anything past the delimiter.
jne noskip
jmp cont ;If no more, then nothing to match.
noskip:
; see if it's "." or "..".
mov DX,DI ;See if the name is all dots.
sub DX,BX
cmp DL,AH
jne notdots
cmp AH,3 ;See if it's one or two dots.
jb exact ;It is all dots---consider it already matched.
notdots:
; see if it's an exact match before searching.
push AX ;Save dot count.
mov byte ptr [DI],0 ;Terminate path.
mov DX,offset path ;Do a find first.
mov CX,17h ;Find any kind of file except labels.
mov AH,4Eh
int 21h
pop AX ;Restore dot count.
jb notexact
test [BP].fattr,10h ;See if it's a directory.
jz notexact
exact:
jmp cont ;Exact match---do next part of argument.
notexact:
; append * or *.* for search.
test AH,AH ;See if any dots in name.
mov AX,'.*'
jnz hasext ;If so, then name has an extension.
stosw ;If no extension, append "*.".
hasext:
mov AH,0 ;Append "*",0.
stosw
; look for a match.
mov DX,offset path ;Do a find first.
mov CX,17h
mov AH,4Eh
int 21h
jb nomatch
tildir: ;Search until a directory matches the name.
test [BP].fattr,10h
jnz ismatch
mov AH,4Fh ;Do a find next.
int 21h
jnb tildir
nomatch: ;Couldn't find one.
mov SI,offset err2
call puts
mov SI,offset path
call puts
mov DX,offset crlf
jmp errx
; got a match, look for a second match.
ismatch:
mov DX,SI ;Save argument pointer.
lea SI,[BP].fname ;Save the name that was found.
lea DI,[BP].tname
mov CX,13
rep movsb
mov SI,DX ;Restore argument pointer.
fndnxt:
mov AH,4Fh ;Do a find next.
int 21h
jb no2nd
test [BP].fattr,10h
jz fndnxt
; got a second match---display the first two and all other
; matches and return with an error.
mov SI,offset path
call puts
mov SI,offset err3
call puts
lea SI,[BP].tname ;Show first match.
call puts
amblp:
mov DL,',' ;Show next match.
mov AH,2
int 21h
lea SI,[BP].fname
call puts
fndlp: ;Look for another match.
mov AH,4Fh ;Do a find next.
int 21h
jb ambfin
test [BP].fattr,10h
jz fndlp
jmp short amblp ;Found another match, show it.
ambfin:
mov DX,offset crlf ;Return with error.
jmp short errx
; no second match, add new match to name.
no2nd:
mov DX,SI ;Save argument pointer.
lea SI,[BP].tname ;Copy matched name to current level in path.
mov DI,BX
cpylp:
movsb
cmp byte ptr [SI],0
jne cpylp
mov SI,DX ;Restore argument pointer.
; loop on parts of specified path (level pointer assumed in DI).
cont:
cmp byte ptr [SI],0 ;See if end of argument.
je argend
cmp byte ptr [SI],' '
je argend
jmp nxtlvl ;More---process it.
argend:
; change to new path.
mov byte ptr [DI],0 ;Terminate path.
mov DX,offset path ;Change directory.
mov AH,3Bh
int 21h
mov DX,offset err4
jb errx
; show the current directory.
showdir:
mov DL,[BP].drv ;Get current directory.
mov SI,offset cmd ;Put it over the command line.
mov AH,47h
int 21h
mov DX,offset err5
jb errx
mov DL,[BP].drv ;Show drive.
add DL,'A'-1
mov AH,2
int 21h
mov DL,':'
int 21h
mov DL,'\'
int 21h
mov SI,offset cmd ;Show current directory.
call puts
mov SI,offset crlf
call puts
int 20h ;Done.
errx:
mov SI,DX
call puts
mov AX,4C01h ;Terminate with error.
int 21h
puts proc near
;
; Send string at SI to stdout.
;
putslp:
lodsb
test AL,AL
jz putsfin
mov DL,AL
mov AH,2
int 21h
jmp short putslp
putsfin:
ret
puts endp
;
; Initialized data -
err1 db 'Invalid drive specification',13,10,0
err2 db 'No such directory ',0
err3 db ' is ambiguous---it matches: ',0
err4 db 'Invalid directory',13,10,0
err5 db 'Unable to determine the current directory'
crlf db 13,10,0
;
; Uninitialized data -
path label byte
c ends
end start