home *** CD-ROM | disk | FTP | other *** search
- page 60,150
- title NJMOVE - Nifty James' MOVE Utility
- subttl (C) 1989 Blaszczak
-
- ;
- ; Nifty James' Famous Move Utility
- ; Version 1.00 of 16 January 1989
- ; (C) Copyright 1989 By Mike Blaszczak
- ;
-
- ;
- ; This file is written for the Microsoft Macro Assembler,
- ; Version 5.10 or higher. The program will not properly
- ; operate under any DOS version less than 2.00, but will
- ; work with any PC-DOS or MS-DOS Versions 2.00 and above.
- ; This is an .EXE file, and should not be run through
- ; EXE2BIN. The executable file should be packed, or the
- ; LINK option /EXEPACK should be used.
- ;
-
-
- ; ----------------------------------------------------------------------------
- ; ASCII Equates
-
- eos equ 000h ; end-of-string character
- bell equ 007h ; bell beeper
- bs equ 008h ; back-space
- tab equ 009h ; tab
- lf equ 00Ah ; line-feed character
- cr equ 00Dh ; carriage return
- ctrlz equ 01Ah ; control zee (aka, EOF)
- eof equ ctrlz
- space equ 020h ; blank space
-
-
- ; ----------------------------------------------------------------------------
- ; DOS Function Calls and constants
-
- INTDOS equ 021h
-
- STDIN equ 0 ; standard output file handle
- STDOUT equ 1 ; standard input file handle
-
- NormalAttrib equ 000h ; normal attribute byte (nothing set)
- SubDirAttrib equ 010h ; attribute for a directory
-
- PutChar equ 002h ; put character to stdout
- GetChar equ 007h ; get char from stdin, with no echo
- GetDefDisk equ 019h ; get current default disk drive
- SetDTA equ 01Ah ; set the DOS DTA address
- FreeSpace equ 036h ; get disk free space
- CreateHandle equ 03Ch ; create a file handle
- OpenHandle equ 03Dh ; open a file handle
- CloseHandle equ 03Eh ; close a file handle
- ReadHandle equ 03Fh ; read from a file or device
- WriteHandle equ 040h ; write to a file or device
- DeleteFile equ 041h ; delete a file name
- GetAttrib equ 04300h ; get file attributes
- SetAttrib equ 04301h ; set file attributes
- IOCTL equ 044h ; I/O control/status call
- GetDefDir equ 047h ; get current default directory
- Terminate equ 04Ch ; terminate this program
- FindFirst equ 04Eh ; find first file matching wildcard
- FindNext equ 04Fh ; find next file matching wildcard
- RenameFile equ 056h ; rename a file
- GetDateTime equ 05700h ; get date or time
- SetDateTime equ 05701h ; set date or time
- NormalizePath equ 060h ; normalize pathname
- GetPSP equ 062h ; get the programs PSP
-
- ; note that NormalizePath is an undocumented call. DS:SI points to a
- ; path specification which may contain a drive specifier. ES:DI points
- ; to a buffer for the normalized pathname. The file simply fixes the
- ; "." and ".." references in the file, making the pathname as short as
- ; possible. This expansion is simply used so the user knows *exactly*
- ; where the file is coming from. Microsoft, in their infinite (heh)
- ; wisdom (hah) did not document this very useful function call.
-
-
- ; ----------------------------------------------------------------------------
- ; ERRORLEVEL values that we return
-
- ERR_None equ 0 ; none!
- ERR_Usage equ 1 ; problem on command line
- ERR_NotFound equ 2 ; file not found
- ERR_BadFile equ 3 ; given a device, or an unparsable
- ERR_CopyProblem equ 4 ; problem while copying
- ERR_Renaming equ 5 ; problem while renaming
-
-
- ; These are the data structures used in this program. The first is used
- ; internally to describe the way a file name is broken down into its
- ; components.
-
- FileDriveLen equ 3
- FilePathLen equ 65
- FileNameLen equ 9
- FileExtLen equ 5
-
- FileNameS struc
- drive db FileDriveLen dup(?) ; drive B:
- path db FilePathLen dup(?) ; path \bin\booger
- fname db FileNameLen dup(?) ; filename njmove
- fext db FileExtLen dup(?) ; extension asm
- FileNameS ends
-
-
- ; This data structure is the one that DOS uses to store the DTA. When
- ; we call FINDFIRST and FINDNEXT, this information will be set up to contain
- ; the rest of the file that we are moving.
-
- DOSDTAS struc
- _dta_reserved db 21 dup (?) ; reserved space
- dta_attribute db ? ; attribute byte
- dta_time dw ? ; file modification time
- dta_date dw ? ; file modification date
- dta_size dd ? ; file size (doubleword!)
- dta_fname db 13 dup (?) ; file name (ASCIIZ)
- DOSDTAS ends
-
-
- ; ============================================================================
- .model small
- .stack 0100h ; get a *real* stack
-
-
- ; ============================================================================
- ; Our data area follows. This data area contains both initialized and
- ; uninitialized data.
-
- .data
-
- Banner db "Nifty James' Famous Move Utility",cr,lf
- db "Version 1.00 of 16 January 1989",cr,lf
- db "(C)Copyright 1989 by Mike Blaszczak",cr,lf
- db lf,eos
-
- NoSpace db "NJMOVE: Destination device ran out of space"
- CRLFSet db cr,lf,eos
-
- NoSelf db "NJMOVE: A File can not be moved into itself"
- db cr,lf,eos
-
- CantWrite db "NJMOVE: Couldn't write to destination device"
- db cr,lf,eos
-
- CantRead db "NJMOVE: Couldn't read from source device"
- db cr,lf,eos
-
- CantSDevice db "NJMOVE: Can't move from a device"
- db cr,lf,eos
-
- CantDDevice db "NJMOVE: Can't move to a device"
- db cr,lf,eos
-
- BadSource db "NJMOVE: Bad Source File Specification"
- db cr,lf,eos
-
- BadDest db "NJMOVE: Bad Destination File Specification"
- db cr,lf,eos
-
- CouldntRename db "NJMOVE: Could not perform rename operation"
- db cr,lf,eos
-
- NameCollide db "NJMOVE: File naming collision; file already exists"
- db cr,lf,eos
-
- CouldntDIR db "NJMOVE: Couldn't get default directory of drive "
- db eos
-
- NoMatches db "NJMOVE: No files matched ",eos
-
- UAborted db cr,lf,"NJMOVE: User Aborted",cr,lf,lf,eos
-
- Usage db "Usage:",cr,lf
- db tab,"NJMOVE <source> <dest> [/C]",cr,lf
- db lf
- db tab,"<source>",tab,"source file name",cr,lf
- db tab,"<dest>",tab,tab,"destination file name",cr,lf
- db tab,tab," both file names may "
- db "contain wildcards",cr,lf
- db tab,"[/C]",tab,"specifies optional confirmation"
- db cr,lf,lf,eos
-
- MovingMess db "Moving ",eos
- MoveCMess db "Move ",eos
-
- CopyingMess db "Copying ",eos
- CopyCMess db "Copy ",eos
-
- ToMess db " to ",eos
-
- BackSlash db "\",eos
-
- DotStar db "."
- Star db "*",eos
-
- ConfirmPrompt db "? [No] ",eos
-
-
- confirmmode db 0 ; set if the /C was to be found
- copymode db 0 ; set to one if we must copy
- ; from disk to disk instead of
- ; just renaming the files
- even
-
- sourcespec dw 0 ; source file specification
- destspec dw 0 ; destination spec
-
- sourcewildf db 0 ; set if sourcef has wildcard name
- sourcewilde db 0 ; set if sourcef has wildcard ext
- sourcehase db 0 ; set if sourcef has extension
- sourcef FileNameS <> ; source description
- sourcefile db 64 dup (0) ; total file name
-
- destwildf db 0 ; set if destf has wildcard name
- destwilde db 0 ; set if destf has wildcard ext
- desthase db 0 ; set if destf has extension
- destf FileNameS <> ; destination description
- destfile db 64 dup (0) ; total file name
-
- mydta DOSDTAS <> ; a place for DOS to store its stuff
- ; during FINDFIRST + FINDNEXT
-
- ; These variables are used by the copyfile procedure
-
- sourceh dw ? ; handle for source file
- desth dw ? ; destination file handle
-
- ; ----------------------------------------------------------------------------
- ; These areas are all data buffers that are not initialized, generally.
-
- even
-
- argvectors dw 64 dup (0) ; pointers to each argumnet
- argcount dw 0 ; count of arguments
- argbuff db 128 dup (0) ; buffer to hold args for DS access
-
- CopyBufferLen equ 16384
- copybuffer db CopyBufferLen dup (?)
- ; this buffer is used while copying
-
- temppath db FilePathLen dup(?)
- ; area used by check4path and
- ; normalizepath
-
- fixedpath db FilePathLen dup(?)
- ; area used by normalize path, too.
-
- ; This area is used by the confirm procedure
-
- confirmreply db ?
-
-
- ; ============================================================================
- ; This is the program code. The execution of the program starts at the
- ; very first instruction here.
-
- .code
-
- ; first, put the banner of our program on the screen
-
- mov ax,@data
- mov ds,ax
- mov si,offset Banner
- call putstr
-
- ; set the DTA to point to our area
-
- mov ah,SetDTA
- mov dx,offset mydta
- int INTDOS
-
- ; then, parse the command line
-
- call parseline
-
- ; convert all of the arguments to upper case
-
- mov ax,@data
- mov ds,ax
-
- mov di,offset argvectors
-
- arguploop: mov si,[di] ; get the next arg
- add di,2
-
- and si,si ; is it 0000?
- je doneargup
-
- call strupr
- jmp short arguploop
-
- doneargup:
- ; then, find the source file and dest file (maybe),
- ; and check for options, too
-
-
- mov di,offset argvectors
- checkargsloop:
- mov si,[di] ; get the next arg
- add di,2
-
- and si,si ; end of list?
- je donecheckargs
-
- mov al,[si] ; nope! check it
- cmp al,'/'
- je gotoption
- cmp al,'-'
- jne notoption
-
- gotoption: inc si ; get the next character of option
- mov al,[si]
- cmp al,'C' ; confirm?
- jne showusage ; nope! error!
-
- mov al,1
- mov confirmmode,al ; confirmation mode
- jmp short checkargsloop
-
- notoption: mov ax,sourcespec ; do we have a source file?
- and ax,ax
- jne gotsource
-
- mov sourcespec,si ; nope! this is our new source spec
- jmp short checkargsloop
-
- gotsource: mov ax,destspec ; how about a dest?
- and ax,ax
- jne showusage
-
- mov destspec,si ; nope! this is the dest spec
- jmp short checkargsloop
-
- ; now, see if we have enough arugments
- donecheckargs:
- mov ax,argcount ; did we get any args?
- and ax,ax
- jne noshowusage ; if not, we must
-
- showusage:
- mov si,offset Usage ; display the usage
- call putstr
- mov ah,Terminate ; and then
- mov al,ERR_Usage ; terminate with error status
- call exit
-
- noshowusage:
- cmp ax,1
- ja gotdest ; was there a destination filespec?
-
- nogotdest:
- mov si,offset Star ; nope. asume dest filespec was
- mov di,offset destf.fname ; *.*
- call strcpy
- mov si,offset DotStar
- mov di,offset destf.fext
- call strcpy
- jmp short destsetup
-
- gotdest: ; yes! call splitfilename to handle
- mov si,destspec ; the parse of the filename
- mov di,offset destf ; into the destf area
- call splitfilename
-
- destsetup:
- ; before we goof with anything, see if the
- ; destination has a file extension
-
- mov si,offset destf.fext
- call strlen
- and cx,cx ; something there?
- je destno
-
- mov al,1
- mov desthase,al ; yes! flag it!
-
-
- destno: mov si,offset destf.drive
- call strlen ; was there a drive name given?
- and cx,cx
- jne gotdestdrive
-
- mov ah,GetDefDisk ; nope-get default from DOS
- int INTDOS
- add al,'A' ; make it ASCII
- mov [si],al
- inc si ; store it
- mov byte ptr [si],':' ; add a colon
- inc si
- mov byte ptr [si],eos ; and a zilcher
-
- gotdestdrive:
- mov si,offset destf.path
- call strlen ; was there a file path?
- and cx,cx
- jne gotdestpath
-
- ; put the default file path into the destf area
- ; first, put a backslash in there
-
- mov di,offset destf.path
- mov si,offset BackSlash
- call strcpy
-
- ; then ask DOS to put the default path into the
- ; copybuffer area
-
- mov si,offset copybuffer
- mov ah,GetDefDir
- mov dl,[destf.drive] ; whats the drive?
- sub dl,('A'-1)
- int INTDOS
- jnc nodestdirproblem
-
- call newline ; print error message
- mov si,offset CouldntDIR
- call putstr
- add dl,('A'-1) ; for that drive
- mov ah,PutChar
- int INTDOS
- call newline
- mov al,ERR_BadFile
- call exit
-
- nodestdirproblem: ; now, concatenate it together. we will end up with
- ; \path\place
-
- mov si,offset copybuffer
- mov di,offset destf.path
- call strcat
-
- ; if the path is not just \, add a trailing \ to it
-
- mov si,offset copybuffer
- call strlen
- cmp cx,1
- jb gotdestpath
-
- mov di,offset destf.path
- mov si,offset BackSlash
- call strcat
-
- gotdestpath:
- ; now, we'll see if the filename is there
-
- mov si,offset destf.fname
- call strlen
- mov bx,cx
-
- mov si,offset destf.fext
- call strlen ; now, cx = strlen(fext)
- ; and bx = strlen(fname)
-
- and cx,cx ; is cx zero?
- je destnoproblem
-
- and bx,bx
- jne destnoproblem
-
- ; we've found that there is no filename but there is an extension.
- ; that's not too good.
-
- mov si,offset BadDest
- call putstr
- mov al,ERR_BadFile
- call exit
-
- destnoproblem:
- and bx,bx ; does filename exist?
- jne desthasfn
-
- mov si,offset Star ; nope ... copy a star there
- mov di,offset destf.fname
- call strcpy
-
- desthasfn:
- and cx,cx ; okay, does the extension exist
- jne destfixed
-
- mov si,offset DotStar; nope, copy ".*" into it
- mov di,offset destf.fext
- call strcpy
-
- destfixed:
- ; now, check to see if there's a wildcard in the filename
- mov si,offset destf.fname
- mov ah,'?'
- call strchr
- and ax,ax ; is it?
- jne desthaswildf
-
- mov si,offset destf.fname
- mov ah,'*' ; how about a star?
- call strchr
- and ax,ax
- je destnowildf
-
- desthaswildf:
- mov al,1
- mov destwildf,al ; set the flag
-
- destnowildf:
- ; see if the destination extension has a wildcard
- mov si,offset destf.fext
- mov ah,'?'
- call strchr
- and ax,ax ; is it?
- jne desthaswilde
-
- mov si,offset destf.fext
- mov ah,'*'
- call strchr
- and ax,ax
- je destdone
-
- desthaswilde:
- mov al,1
- mov destwilde,al
-
- destdone: ; normalize the path for the destf
-
- mov si,offset destf
- call normpath
-
- ; does the filename have a wildcard?
-
- mov al,destwildf
- and al,al
- jne destcompleted
-
- ; does it have an extension?
-
- mov al,desthase
- and al,al
- jne destcompleted
-
- ; if not, check to see if the filename is a directory
-
- mov si,offset destf
- call check4dir
- and ax,ax ; did it work?
- je destcompleted
-
- mov destwilde,al ; yes! extension and filename
- mov destwildf,al ; are wildcards now
-
- destcompleted: ; the destination file is all set up!
- ; now, we can parse the source file name
-
- mov si,sourcespec
- mov di,offset sourcef
- call splitfilename
-
- ; before we touch anything, see if we were given
- ; a file extension
-
- mov si,offset sourcef.fext
- call strlen
- and cx,cx ; anything there?
- je sourceno
-
- mov al,1
- mov sourcehase,al ; yes! flag it
-
-
- sourceno: ; check 'n' see if there is a drive there
-
- mov si,offset sourcef.drive
- call strlen
- and cx,cx
- jne gotsourcedrive
-
- mov ah,GetDefDisk ; nope-get default from DOS
- int INTDOS
- add al,'A'
- mov [si],al
- inc si
- mov byte ptr [si],':' ; and store a colon after it
- inc si
- mov byte ptr [si],eos ; and a zilcher around it
-
- gotsourcedrive:
- mov si,offset sourcef.path
- call strlen ; was there a file path?
- and cx,cx
- jne gotsourcepath
-
- ; put the default file path into the sourcef area
- ; first, put a backslash in there
-
- mov si,offset BackSlash
- mov di,offset sourcef.path
- call strcpy
-
- ; then ask DOS to put the default path into the
- ; copy buffer area
-
- mov si,offset copybuffer
- mov ah,GetDefDir
- mov dl,[sourcef.drive] ; whats the drive?
- sub dl,('A'-1) ; make into A=1, B=2 ... for DOS
- int INTDOS
- jnc nosourcedirprob
-
- call newline ; print error message
- mov si,offset CouldntDIR
- call putstr
- add dl,('A'-1) ; for that drive
- mov ah,PutChar
- int INTDOS
- call newline
- mov al,ERR_BadFile
- call exit
-
- nosourcedirprob: ; now, concatenate it togethre
-
- mov si,offset copybuffer
- mov di,offset sourcef.path
- call strcat
-
- ; if the path is not just \, add a trailing \ to it
- mov si,offset copybuffer
- call strlen
- cmp cx,1
- jb gotsourcepath
-
- mov di,offset sourcef.path
- mov si,offset BackSlash
- call strcat
-
- gotsourcepath:
- ; make sure there's a filename, even if its a wildcard.
- ; check that it was a valid filename, too.
-
- mov si,offset sourcef.fname
- call strlen
- mov bx,cx
-
- mov si,offset sourcef.fext
- call strlen ; now, cx = strlen(fext)
- ; and bx = strlen(fname)
-
- and cx,cx
- je sourcenoproblem
-
- and bx,bx
- jne sourcenoproblem
-
- ; we've found that there is no filename but there is an extension
- ; that's not good
-
- mov si,offset BadSource
- call putstr
- mov al,ERR_BadFile
- call exit
-
- sourcenoproblem:
- and bx,bx ; does filename exist?
- jne sourcehasf
-
- mov si,offset Star ; nope ... copy a astar in there
- mov di,offset sourcef.fname
- call strcpy
-
- sourcehasf:
- and cx,cx ; does extension exist?
- jne sourcedone
- mov si,offset DotStar
- mov di,offset sourcef.fext
- call strcpy
-
- ; now, check to see if there's a wildcard in the filename
- mov si,offset sourcef.fname
- mov ah,'?'
- call strchr
- and ax,ax ; is it?
- jne sourcehaswildf
-
- mov si,offset sourcef.fname
- mov ah,'*' ; how about a star?
- call strchr
- and ax,ax
- je sourcenowildf
-
- sourcehaswildf:
- mov al,1
- mov sourcewildf,al ; set the flag
-
- sourcenowildf:
- ; see if the sourceination extension has a wildcard
- mov si,offset sourcef.fext
- mov ah,'?'
- call strchr
- and ax,ax ; is it?
- jne sourcehaswilde
-
- mov si,offset sourcef.fext
- mov ah,'*'
- call strchr
- and ax,ax
- je sourcedone
-
- sourcehaswilde:
- mov al,1
- mov sourcewilde,al
-
- sourcedone: ; last, normalize the source file path
-
- mov si,offset sourcef
- call normpath
-
- mov al,sourcewildf
- and al,al
- jne sourcecompleted
-
- mov al,sourcehase
- and al,al
- jne sourcecompleted
-
- mov si,offset sourcef
- call check4dir
- and ax,ax ; did it work?
- je sourcecompleted
-
- mov sourcewildf,al ; yes! filename and
- mov sourcewilde,al ; extension are now wildcards!
-
-
- sourcecompleted: ; filenames are all set!
- ; okay, almost there! check to see if the drives
- ; are the same. if they are, we're renaming. if
- ; they're not, we're copying and deleting.
-
- mov si,offset sourcef.drive
- mov al,[si]
- mov si,offset destf.drive
- cmp al,[si]
- je workhorse
-
- mov al,1 ; set copying flag
- mov copymode,al
-
- ; right! everything is ready. we'll make the source
- ; file name into something meaningful
-
- workhorse: mov si,offset sourcef
- mov di,offset sourcefile
- call makefilename
-
- ; just for kicks, we'll try to open that file.
-
- mov ah,OpenHandle
- mov al,0
- mov dx,offset sourcefile
- int INTDOS
-
- jc dothefindfirst
-
- mov bx,ax
- mov ah,IOCTL
- mov al,0 ; see if it is a device
- int INTDOS
-
- and dx,0080h ; check ISDEV bit
- je notdevice
-
- deviceblowout: mov si,offset CantSDevice
- call putstr
- mov ax,ERR_BadFile
- call exit
-
-
- notdevice: mov ah,CloseHandle
- int INTDOS
-
-
- ; we'll try to find the first matching file
-
- dothefindfirst: mov ah,FindFirst
- mov dx,offset sourcefile
- xor cx,cx
- int INTDOS
-
- jnc foundone
-
- notfound: mov si,offset NoMatches
- call putstr
- mov si,offset sourcefile
- call putstr
- call newline
- mov ax,ERR_NotFound
- call exit
-
- ; this loop is the main thing. we've called findfirst,
- ; and the dta block is set up with the file we found.
- ; we'll figure out the destination file name, and
- ; then move or copy the file.
-
- ; at the bottom of the loop, we'll call findnext and
- ; see if there are more matching files. if its there,
- ; we can loop back here and process that next file.
-
- foundone: mov si,offset mydta
- mov di,offset sourcef
- call popfound
- mov si,offset sourcef
- mov di,offset sourcefile
- call makefilename
-
- ; if the source filename has a wildcard *and* the
- ; dest filename has a wild card, copy source filename
- ; into the destination filename
-
- mov al,destwildf
- and al,al
- je notwildf
-
- mov si,offset sourcef.fname
- mov di,offset destf.fname
- call strcpy
-
-
- notwildf: ; if the source file extension has a wildcard, and
- ; the destination extension has a wildcard, copy
- ; the source extension into the destination extension
-
- mov al,destwilde
- and al,al
- je notwilde
-
- mov si,offset sourcef.fext
- mov di,offset destf.fext
- call strcpy
-
-
- notwilde: ; create the destination file into an ASCIIZ string
-
- mov si,offset destf
- mov di,offset destfile
- call makefilename
-
- ; print a message for what we are going to do
-
- mov al,copymode
- mov ah,confirmmode
-
- and al,al
- je wearemoving
-
- mov si,offset CopyingMess ; we're copying
-
- and ah,ah
- je printsource ; without confirmation
-
- mov si,offset CopyCMess
- jne printsource
-
- wearemoving: mov si,offset MovingMess ; we're moving
- and ah,ah
- je printsource ; without confirmation?
-
- mov si,offset MoveCMess
-
-
- printsource: call putstr
-
- ; either
- ; "Moving sourcefile to destfile"
- ; or
- ; "Copying sourcefile to destfile"
-
- mov si,offset sourcefile
- call putstr
-
- whereto: ; print " to "
-
- mov si,offset ToMess
- call putstr
-
- mov si,offset destfile
- call putstr
-
-
- ; before we actually do it, call confirmation, if need be
-
- and ah,ah
- jne askfirst ; no confirmation
-
- call newline
- jmp short goahead
-
- askfirst: call getyesno ; do confirmation
- call newline
-
- cmp ax,0 ; no?
- je loopbottom ; skip it, then
-
- cmp ax,1 ; yes?
- je goahead ; go right ahead
-
- xor ax,ax ; all of them!
- mov confirmmode,al ; (forget about confirming)
-
- ; actually do it
-
- goahead: mov al,copymode
- and al,al
- jne doacopy
-
- doamove:
- mov dx,offset sourcefile
- mov di,offset destfile
- mov ah,RenameFile
- int INTDOS
- jnc loopbottom
-
- ; decide which error happened. AX=0005 is bad name,
- ; anything else is different.
-
- mov bx,ax
- mov al,ERR_Renaming
-
- mov si,offset NameCollide
- cmp bx,5
- je renamingcollision
-
- mov si,offset CouldntRename
-
- renamingcollision: call newline
- call putstr
- mov ah,ERR_Renaming
- call exit
-
- doacopy: call copyfile
-
- loopbottom: mov ah,FindNext
- int INTDOS
- jc cleanexit ; relative jnc out of range
- jmp foundone
-
-
-
-
- cleanexit:
- mov al,ERR_None ; return with no error
- call exit
-
-
-
- ; ============================================================================
- ; These subroutines are used by the programs' main routine
-
-
- ; ----------------------------------------------------------------------------
- ; exit
- ; On entry, AL contains the error level that the program should return.
- ;
- ; This routine will terminate to DOS. It does no housekeeping functions.
-
- exit proc near
-
- mov ah,Terminate ; make a Terminate call
- int INTDOS
-
- exit endp
-
-
- ; ----------------------------------------------------------------------------
- ; strlen
- ; On entry, DS:SI points to a string.
- ;
- ; On return, CX will contain the length of the string.
-
- strlen proc near
-
- push ax
- push si
-
- xor cx,cx ; zero the length count
-
- sl_c: mov al,[si] ; get a character
- inc si
- inc cx ; increment pointer and count
- and al,al ; is it end of string?
- jne sl_c ; loop back if it isn't
-
- dec cx ; adjust the count down
-
- pop si
- pop ax
- ret
-
- strlen endp
-
-
-
- ; ----------------------------------------------------------------------------
- ; newline
- ; This routine prints a carriage return and a linefeed. We will destroy
- ; no registers.
-
-
- newline proc near
-
- push si
- push ds ; save the DS:SI
- push ax
-
- mov ax,@data
- mov ds,ax
- mov si,offset CRLFSet
- call putstr
-
- pop ax ; restore the registers
- pop ds
- pop si
- ret
-
- newline endp
-
-
- ; ----------------------------------------------------------------------------
- ; putstr
- ; On entry, DS:SI points to a string.
- ;
- ; This routine prints the passed string to STDOUT, and does nothing else.
- ; The string is not altered in any way.
-
- putstr proc near
-
- push dx
- push cx
- push bx
- push ax ; save the regs we use
- push si
-
- xor cx,cx ; zero the length count
-
- ps_l: mov al,[si] ; get a character
- inc si
- inc cx ; increment pointer and count
- and al,al ; is it end of string?
- jne ps_l ; loop back if it isn't
-
- dec cx ; adjust the count down
-
- mov ah,WriteHandle ; ask DOS to write to the stdout
- mov bx,STDOUT
-
- pop si ; restore the SI
- mov dx,si ; and put it into dx for DOS
- int INTDOS
-
- pop ax
- pop bx
- pop cx
- pop dx
- ret
-
- putstr endp
-
-
- ; ----------------------------------------------------------------------------
- ; strcat
- ; On entry, DS:SI points to the concatenant, and ES:DI points to the
- ; concatenand:
- ;
- ; DS:SI -> "Have Antlers"
- ; ES:DI -> "Mooses "
- ; call strcat
- ; ES:DI -> "Mooses Have Antlers"
-
-
- strcat proc near
-
- push ax
- push si ; save the registers
- push di
-
- ; first, find the end
-
- sc_next: mov al,es:[di] ; get the char
- inc di
- and al,al ; is it zilcher?
- jne sc_next ; nope ... keep looping
-
- dec di ; point to the zilcher
-
- ; now, we can just call strcpy to move the concatenant
- ; over the end of the concatenand.
-
- call strcpy
-
- pop di
- pop si
- pop ax
-
- ret
- strcat endp
-
-
- ; ----------------------------------------------------------------------------
- ; strcpy
- ; On entry, DS:SI points to a string and ES:DI points to storage space.
- ;
- ; This routine will copy the string from DS:SI to ES:DI.
-
- strcpy proc near
-
- push di ; save the registers we use
- push si
- push ax
-
- sc_nextc: mov al,[si] ; get another character
- inc si
- mov es:[di],al ; store it
- inc di
-
- and al,al ; if that was the 0 character, quit
- jne sc_nextc ; else keep working on the string
-
- pop ax ; restore the registers we used
- pop si
- pop di
- ret
- strcpy endp
-
-
- ; ----------------------------------------------------------------------------
- ; strchr
- ; On entry, DS:SI points to a string, and ah contains a character to match.
- ; The routine will work forward through the string until it finds the end
- ; of the string or matches the character. On return, AX will be 0000 if
- ; there was no match, or DS:AX will point to the character in the string
- ; if the character wasn't found.
-
- strchr proc near
-
- push si ; save si
-
- strchrnc: mov al,[si] ; get a character
- inc si ; and increment pointer
- cmp al,ah ; is it a match?
- je strchrhit
-
- and al,al ; nope. was it '\0'?
- jne strchrnc ; if not, go do more
-
- xor ax,ax ; yes, the string ended
- je strchrexit ; so make AX null for failure
-
- strchrhit: mov ax,si ; got the character!
- dec ax ; put pointer into ax
-
- strchrexit: pop si ; restore si
- ret ; and go home
-
- strchr endp
-
-
- ; ----------------------------------------------------------------------------
- ; strrchr
- ; On entry, DS:SI points to a string, and ah contains a character to match.
- ; The routine will step backward, starting at the end of the string, and
- ; work until it finds a match. If the program makes it through the whole
- ; string without finding the character, it will return with AX set to 0000.
- ; Otherwise, DS:AX points the the last occurrence of the character in the
- ; string.
-
-
- strrchr proc near
-
- push cx ; save the registers we use
- push si
- xor cx,cx ; zero cx since we use it to count
-
- strrchrfe: mov al,[si] ; get the next character
- inc si ; increment the pointer
- inc cx ; increment the count of chars
- and al,al ; is this the end of the string?
- jne strrchrfe
-
- cmp cx,0 ; is the string empty?
- je strrchrfail ; if so, automatic failure
-
- strrchrloop: dec si ; point to the null
- mov al,[si] ; is that the character?
- cmp ah,al
- je strrchrhit ; if so, we've hit!
- dec cx
- jne strrchrloop ; if not, loop more
-
- strrchrfail: xor ax,ax
- je strrchrexit ; return AX as 0000
-
- strrchrhit: mov ax,si ; got the character! move pointer
- ; into ax
-
- strrchrexit: pop si
- pop cx
- ret
-
- strrchr endp
-
-
- ; ----------------------------------------------------------------------------
- ; strupr
- ; On entry, DS:SI points to a string and ES:DI points to storage space.
- ;
- ; This routine will convert the entire content of the string to uppercase.
- ; It won't alter any registers, nor will it change non-alphabetic characters
- ; in the str.
-
-
- strupr proc near
-
- cld
- push ax
- push si
-
- struprloop: lodsb ; get the next character
- and al,al ; is it zilcho?
- je struprdone
-
- cmp al,'a' ; is it less than 'a'?
- jl struprloop ; yep ... keep looping
-
- cmp al,'z' ; is it bigger than 'z'?
- jg struprloop ; yes; don't modify it
-
- sub al,('a' - 'A')
- mov [si-1],al ; restore that character
- jmp short struprloop
-
- struprdone: pop si
- pop ax
- ret
-
- strupr endp
-
-
- ; ----------------------------------------------------------------------------
- ; parseline
- ; This routine tries to parse the command line. It sets up the variables
- ; in the data segment (argcount and arglist), as well as copying the
- ; information into a local area in the data segment. The routine will
- ; not preserve any of the registers it uses.
-
- parseline proc near
-
- mov ah,GetPSP ; get the PSP from DOS
- int INTDOS
-
- mov ds,bx ; move the PSP into ds
- mov si,0081h ; address the command line
-
- xor dx,dx
- mov dl,[si-1] ; get the length of the line
- add dl,081h
-
- mov ax,@data ; now, set up ES to point to our
- mov es,ax ; own data areas
- mov di,offset argbuff
-
-
- nextarg:
- eatwhite:
- mov al,[si]
- inc si ; get the next character
-
- cmp al,space ; is it a space?
- je eatwhite
- cmp al,tab ; or a tab?
- je eatwhite ; yes ... skip over it
-
- dec si ; point si at the first non-white
- push si ; and save a copy of it for later
-
- eatarg: mov al,[si] ; get the last character
- inc si
- cmp al,space ; is it a whitespace?
- jle gotarg
- jmp short eatarg ; nope... keep skipping
-
- gotarg:
- dec si
- mov byte ptr [si],0 ; make the argument a string
-
- pop ax ; get the pointer to this arg
-
- xchg ax,si ; put si into DS:SI
-
- call strcpy ; store in our data segment
-
- call strlen ; get the length of the string
- push cx ; save it
-
- xchg si,ax
-
- and cx,cx ; if this string has no length,
- je added ; don't add it to the table
-
- ; here, DS:AX points to the end of the string and
- ; ES:DI points to the place where the string was stored.
- ; DS:SI still points to the beginning of the string.
-
- add2table: mov ax,es:argcount
- shl ax,1 ; get offset into array
- add ax,offset argvectors
- xchg ax,si
- mov es:[si],di ; store the offset of this arg
- xchg si,ax
-
- inc es:argcount ; increment the count of args
-
- added:
- ; adjust ES:DI
-
- pop cx
- add di,cx ; get the length and fix it in
- inc di ; make DS:SI point to the next
- inc si ; free spot
-
- ; see if we are done
-
- cmp dx,si
- ja nextarg
-
- wearedone:
- ret
- parseline endp
-
-
- ; ----------------------------------------------------------------------------
- ; splitfilename
- ; this procedure accepts ds:si as a pointer to a full file name. it also
- ; expects that es:di points to a FileNameS. The routine will copy
- ; information from the full file name into the FileNameS structure.
-
- splitfilename proc near
-
- push cx
- push si ; save the regs we use
- push di
-
- ; to get started, check to see if there's a drivespec
-
- mov al,[si+1] ; is there a colon for the
- cmp al,':' ; second character?
- jne sfn_nodrive ; nope! don't worry about it
-
- sfn_gotdrive: mov es:[di+1].drive,al ; store the colon
- mov al,[si] ; get the drive letter
- mov es:[di].drive,al
- add di,2 ; make es:di point after it
- add si,2 ; and make si point after drive
-
-
- sfn_nodrive: ; since there's no drive spec, just zero the drive.
-
- xor ax,ax
- mov es:[di].drive,al ; stick it
-
-
- sfn_drivedone: ; now that drive is done, point es:di to the path
-
- pop di ; point to the path area
- push di
- add di,path
-
- ; see if there was a path in the filename we got
-
- mov al,[si] ; get the first char
- cmp al,'.'
- jne sfn_notrelpath
- je sfn_hasrelpath
-
-
- sfn_notrelpath: mov ah,'\' ; the path character
- call strchr
-
- and ax,ax ; is AX == 0000?
- jne sfn_haspath
-
- sfn_hasrelpath: mov ax,si ; yes -- point to the start of
- ; the string
-
- sfn_haspath: ; there's a path! now, try to find the *last*
- ; character of the path.
-
- mov dx,ax ; save AX for now
- mov ah,'\'
- call strrchr ; find the last '\'
- xchg ax,dx
-
- and dx,dx
- jne sfn_hasend
-
- ; hmph! there is no '\', either way you look
- ; does the path begin with '.'?
-
- cmp byte ptr [si],'.'
- jne sfn_nopath ; nope! no path name
- ; yes! relative path name!
-
-
- sfn_relpath: call strlen ; if no '\', point to end of
- mov dx,si ; string
- add dx,cx
-
- cmp ax,dx ; is our end and start equal?
- je sfn_nopath ; no path here, mon!
-
- ; now, copy the string from DS:AX to DS:DX into ES:DI.
-
- sfn_hasend: mov si,ax ; start with ax
- mov cx,FilePathLen-2
-
- sfn_movepath: mov al,[si]
- inc si ; get this character
- mov es:[di],al ; and store it in path
- inc di
-
- dec cx ; decrement max char count.
- jne sfn_movingpath ; if too many, truncate
-
- mov al,'\'
- mov es:[di],al ; truncate with a backslash
- inc di
- mov si,dx ; update the pointer so's it
- inc si ; points to the filename now
- jmp short sfn_movedpath
-
- sfn_movingpath:
- cmp dx,si ; is si>dx? (work to dx)
- jae sfn_movepath ; no ... keep looping
-
- sfn_movedpath:
- sfn_nopath: xor ax,ax ; set up the ax so we can
- mov es:[di],al ; store a null in .path area
-
- ; now, we have the path done. mess with moving
- ; the file name and the extension. DS:SI already
- ; points to the file name.
-
- sfn_pathdone: pop di ; make es:di point to filename
- push di
- add di,fname
-
- mov cx,FileNameLen
-
- sfn_movefn: mov al,[si] ; get the next character
- cmp al,'.' ; end of filename?
- je sfn_gotext
-
- dec cx ; too many characters?
- jne sfn_moveingfn ; yep! truncate.
-
- mov al,0
- mov es:[di],al ; terminate the filename
- sfn_blowoff: mov al,[si] ; skip ahead until we find eos or
- cmp al,'.' ; a period
- je sfn_gotext
- inc si
- and al,al ; is it a zilcher?
- jne sfn_blowoff
- je sfn_movedfn
-
- sfn_moveingfn:
- mov es:[di],al ; store this character
- inc si
- inc di
- and al,al ; did we just write an eos?
- jne sfn_movefn
-
- sfn_movedfn: xor ax,ax
- pop di ; make addressing to strucutre
- push di
- mov es:[di].fext,al
- jmp short sfn_exit ; and split this joint
-
- sfn_gotext: mov ah,0 ; write an end-of-string for
- mov es:[di],ah ; the filename, first
-
- mov cx,FileExtLen
-
- pop di
- push di
- add di,fext ; make es:di point to filename
-
- sfn_moveext: mov es:[di],al ; store the character
- inc si
- inc di ; increment the pointers
- and al,al ; did we just write a '\0'?
- je sfn_exit
-
- cmp cx,0 ; is it zero yet?
- jne snf_movingext
-
- mov al,0
- dec di
- mov es:[di],al
- jmp short sfn_exit
-
- snf_movingext: dec cx
- mov al,[si] ; get next character
- jmp short sfn_moveext
-
- sfn_exit:
- ; on the way out, we will check to see if the path
- ; name was a relative file. if so, we will make
- ; sure a slash is appended to it.
-
- pop di
- push di
- add di,path
-
- mov al,[di]
- cmp al,'.' ; not a relative, no problem
- jne sfn_nofix
-
- ; fix relative path
-
- mov si,di
- call strlen
- add si,cx
- dec si ; point to last character
- mov al,[si] ; get that character
- cmp al,'\' ; slash?
- je sfn_nofix ; no problem
-
- inc si ; make it a slash
- mov byte ptr [si],'\'
- inc si
- mov byte ptr [si],eos
-
- sfn_nofix: ; restore the regs we saved
- pop di
- pop si
- pop cx
- ret
- splitfilename endp
-
-
- ; ----------------------------------------------------------------------------
- ; makefilename
- ; On entry, DS:SI points to a FileNameS, and ES:DI points to a storage
- ; buffer for a file name. The routine will string all of the elements
- ; of the strucutre together to make a real full file name.
-
- makefilename proc near
-
- push ax
- push si
- push di
- mov ax,si ; put base pointer into ax
-
- ; first copy the drive specifier
-
- mov si,ax
- add si,drive ; copy the drive
- call strcpy
-
- ; then concatenate the path
-
- mov si,ax
- add si,path
- call strcat
-
- ; then concatenate the filename
-
- mov si,ax
- add si,fname
- call strcat
-
- ; now concatenate the extension
-
- mov si,ax
- add si,fext
- call strcat
-
- ; that's all!
-
- pop di
- pop si ; restore the registers and return home
- pop ax
- ret
- makefilename endp
-
-
- ; ----------------------------------------------------------------------------
- ; popfound
- ; This routine accepts a pointer to a DOSDTAS in DS:DI, and a pointer to
- ; a FileNameS in ES:DI. It takes the filename and extension fields from
- ; the DOSDTAS and puts them into the fname and fext portions of the
- ; FileNameS structure.
-
- popfound proc
-
- push ax
- push cx
- push dx
- push si ; save the regs we use
- push di
-
- mov dx,si ; and make a copy of the parms
- mov cx,di ; to easily address the structs
-
- ; first, work on moving the filename
-
- mov si,dx
- add si,dta_fname
-
- mov di,cx
- add di,fname
-
- popfoundf: mov al,[si] ; get this char
- cmp al,'.' ; period yet?
- je popfounde
- mov es:[di],al ; store it
-
- and al,al ; is it a zilcher?
- jne popfoundfing
-
- mov di,cx ; yep! zilch out extension too
- add di,fext
- mov es:[di],al
- jmp short popfounddone
-
-
- popfoundfing: inc di
- inc si
- jmp short popfoundf ; loop for more
-
- popfounde: mov ah,0
- mov es:[di],ah ; terminate the filename with 0
- mov di,cx
-
- add di,fext ; point to the extension
-
- popfoundw: mov es:[di],al
- inc di
- inc si
- and al,al ; is it zero?
- je popfounddone ; yes, quit!
- mov al,[si] ;(get next char)
- jne popfoundw ; nope ... keep working
-
- popfounddone:
- pop di
- pop si ; restore registers
- pop dx
- pop cx
- pop ax
- ret
- popfound endp
-
-
- ; ----------------------------------------------------------------------------
- ; copyfile
- ; this procedure completely copies a file. it copies the file in
- ; sourcefile to the file in destfile. If there is an error during
- ; the copy, the destfile is automatically deleted and the program
- ; terminates via exit. If the copy is successful, the source file
- ; is deleted. The dest file will inherit the same file time and
- ; date stamp as the source file.
-
- copyfile proc near
-
- ; first, try to open the dest file for reading
-
- mov ah,OpenHandle ; open the
- mov dx,offset destfile ; dest for
- mov al,0 ; reading
- int INTDOS
- jc cf_nameokay
-
- ; we could read the source file! the file already
- ; exists, so we must abort.
-
- mov bx,ax
- mov ah,CloseHandle ; close the handle and
- call newline
- mov si,offset NameCollide ; print an error!
- call putstr
- mov ah,ERR_CopyProblem
- call exit
-
- cf_nameokay: ; try to open the source file
-
- mov ah,OpenHandle ; open the
- mov dx,offset sourcefile ; source for
- mov al,0 ; for reading
- int INTDOS
-
- ; was there an error?
-
- jnc cf_noopenerr
-
- cf_cantread: call newline ; couldn't open; print
- mov si,offset CantRead ; an error message
- call putstr
- mov ah,ERR_CopyProblem
- call exit ; and terminate
-
- cf_noopenerr: mov sourceh,ax ; save the handle
-
- mov ah,CreateHandle ; open
- mov dx,offset destfile ; desination
- xor cx,cx ; no attribute
- int INTDOS
-
- jnc cf_nowriteopen
-
- cf_cantwrite: call newline ; couldn't write; print
- mov si,offset CantWrite ; an error message
- call putstr
- mov ah,ERR_CopyProblem
- call exit ; and terminate!
-
- cf_nowriteopen: mov desth,ax
-
- cf_nextbunch: mov ah,ReadHandle ; read
- mov cx,CopyBufferLen ; all we can
- mov bx,sourceh ; from the source
- mov dx,offset copybuffer ; into the buffer
- int INTDOS
-
- jnc cf_canread ; no read error?
-
- mov dx,offset destfile ; delete the dest file
- mov ah,DeleteFile
- int INTDOS
- jmp short cf_cantread ; print error and quit
-
- cf_canread:
- and ax,ax ; (Was it zero?)
- je cf_closeup ; yes! go close the files
-
- mov cx,ax ; take what we read
- mov ah,WriteHandle ; and write it
- mov dx,offset copybuffer ; from the buffer
- mov bx,desth ; to the destination
- int INTDOS
-
- jnc cf_canwrite ; write error!
-
- mov dx,offset destfile ; delete the dest file
- mov ah,DeleteFile
- int INTDOS
- jmp short cf_cantwrite ; print error and quit
-
- cf_canwrite:
- cmp cx,ax ; did we write 'em all?
- jne cf_cantwrite ; no? that's a problem!
- je cf_nextbunch
-
- cf_closeup:
- mov ax,GetDateTime ; get the date
- mov bx,sourceh ; from the source file
- int INTDOS
-
- mov ax,SetDateTime ; set the date
- mov bx,desth ; to the dest file
- int INTDOS
-
- mov bx,desth ; close dest file
- mov ah,CloseHandle
- int INTDOS
-
- mov bx,sourceh ; close source file
- mov ah,CloseHandle
- int INTDOS
-
- ; get the source file's attribute byte
-
- mov dx,offset sourcefile
- mov ax,GetAttrib
- int INTDOS
-
- ; set the dest file's attribute byte
-
- mov dx,offset destfile
- mov ax,SetAttrib ; CX is already set
- or cx,020h ; but set archive bit
- int INTDOS
-
- ; set the source file's attribute byte to normal
-
- mov dx,offset sourcefile
- mov ax,SetAttrib
- mov cx,NormalAttrib ; reset source file
- ; so we can now
- mov dx,offset sourcefile ; delete the source file
- mov ah,DeleteFile
- int INTDOS
-
- ret
- copyfile endp
-
-
- ; ----------------------------------------------------------------------------
- ; getyesno
- ; This procedure prints a yes/no prompt on the screen and gets an answer.
- ; the routine accepts "y", "1", and "t" as affirmative responses. the
- ; routine accepts "n", "0", and "f" as negative responses. If the routine
- ; is given an affirmative response, it will return AX as 0001. If it is
- ; given a negative reply, it will send back 0000 in AX. If the routine
- ; receives "a" in reply to its prompt, it will return a 0002 in AX.
-
- getyesno proc near
-
- mov si,offset ConfirmPrompt ; print prompt
- call putstr
-
- gyn_delete: xor ax,ax
- mov confirmreply,al
-
- gyn_loop: mov ah,GetChar ; get one character
- int INTDOS
- cmp al,'a'
- jl gyn_noup
- cmp al,'z'
- jg gyn_noup
-
- sub al,('a'-'A') ; make it uppercase
-
- gyn_noup: mov ah,confirmreply
- and ah,ah
- jne gyn_checkcr ; we got a letter, is this one
- ; a carriage return?
-
- cmp al,cr ; carriage return?
- je gyn_negative ; yep, default is no!
-
- cmp al,ctrlz ; control zee?
- jne gyn_notzee
-
- ; if CTRL+Z is pressed, we must quit here.
-
- mov si,offset UAborted
- call putstr ; make a message about it
- mov al,ERR_None ; exit with no errors
- call exit
-
- gyn_notzee: cmp al,space ; is this character lower than ' '?
- jle gyn_loop ; yep, ignore it
-
- cmp al,'Y' ; filter out unwanted chars
- je gyn_okay ;
-
- cmp al,'N'
- je gyn_okay
-
- cmp al,'A'
- je gyn_okay
-
- cmp al,'0'
- je gyn_okay
-
- cmp al,'1'
- je gyn_okay
-
- cmp al,'T'
- je gyn_okay
-
- cmp al,'F'
- jne gyn_loop
-
- gyn_okay:
- mov confirmreply,al ; store the character
-
- mov ah,PutChar ; and echo it to the screen
- mov dl,al
- int INTDOS
- jmp short gyn_loop ; go loop back for more
-
- gyn_checkcr: cmp al,cr ; is this one a carriage return?
- je gyn_replied ; yes! process the reply
-
- cmp al,bs ; is this one a backspace?
- jne gyn_loop ; no! bad char, ignore it
-
- mov ah,PutChar ; put a backspace
- mov dl,bs
- int INTDOS
-
- mov ah,PutChar ; put a space to whiteout
- mov dl,space ; the character typed
- int INTDOS
-
- mov ah,PutChar ; and another BS to fix cursor
- mov dl,bs
- int INTDOS
-
- jmp gyn_delete
-
- gyn_replied: mov al,confirmreply ; get the reply, and decide what
- ; to do
-
- cmp al,'A'
- je gyn_everything
-
- cmp al,'0'
- je gyn_negative
- cmp al,'F'
- je gyn_negative
- cmp al,'N'
- je gyn_negative
-
- cmp al,'Y'
- je gyn_affirm
- cmp al,'1'
- je gyn_affirm
- cmp al,'T'
- je gyn_affirm
- jmp gyn_loop ; somehow a bad char got in
-
-
- gyn_everything: mov ax,2 ; reply "all"
- ret
-
- gyn_negative: mov ax,0 ; negative reply
- ret
-
- gyn_affirm: mov ax,1 ; affirmative reply
- ret
-
- getyesno endp
-
-
- ; ----------------------------------------------------------------------------
- ; check4dir
- ; this routine accepts DI as a pointer to a FileNameS. It will check
- ; to see if the file name section of the file name is actually a directory.
- ; if it is, it will move the file name to the end of the path field and
- ; make the file name null. if not, it simply returns without changing
- ; the structure. We have to do this because DOS won't understand us if
- ; we specify a subdirectory without tacking \*.* onto the end of it.
- ; If we end up changing anything, AX is set to one. If not, AX is zilch.
- ;
-
- check4dir proc near
-
- push si ; save the pointer
-
- mov di,offset temppath
- call strcpy ; move drive to temppath
-
- mov di,offset temppath
- add si,path ; get the path
- call strcat
-
- mov di,offset temppath
- pop si
- push si
- add si,fname
- call strcat ; and finally add the filename
-
- mov ah,FindFirst
- mov dx,offset temppath
- mov cx,SubDirAttrib ; get directories only
- int INTDOS
- jnc c4d_worked
-
- ; return with al set to zero to indicate that
- ; we didn't change the filename
-
- xor ax,ax ; make a zilcher out of ax
- pop si
- ret
-
- ; it *is* a subdir!
- ; concatenate the file to the path
-
-
- c4d_worked: pop si
- push si
- mov di,si
- add di,path
- add si,fname
- call strcat ; add filename to path
-
- mov si,offset BackSlash
- call strcat ; add backslash to path
-
- mov si,offset Star ; put a star into the filename
- pop di
- push di
- add di,fname
- call strcpy
-
- mov si,offset DotStar
- pop di
- push di
- add di,fext ; and a ".*" into extension
- call strcpy
-
- c4d_end: mov ax,1 ; ax=1, success!
- pop si ; pop register and return!
- ret
- check4dir endp
-
-
- ; ----------------------------------------------------------------------------
- ; normpath
- ; this proc accepts a pointer to a FileNameS in DS:SI. The proc will
- ; call DOS to have it normalize the path -- this simply means that the
- ; procedure will resolve any relative (ie, including "." or "..")
- ; file path references. Note that the function call used here is
- ; undocumented.
-
- normpath proc near
-
- push di ; save the registers
- push si
-
-
- mov di,offset temppath
- call strcpy ; copy drive and path to
- add si,path ; a temporary area
- call strcat
-
- mov ah,NormalizePath
- mov si,offset temppath
- mov di,offset fixedpath
- int INTDOS
-
- pop si
- mov di,si ; copy the path back
- add di,path
- mov si,(offset fixedpath)+2
- call strcpy
-
- pop di ; restore
- ret ; and return
- normpath endp
-
-
- ; ----------------------------------------------------------------------------
- ; That's a wrap. Written under the influence of Tom Petty, Rush, and REM.
-
- end
-