MS-DOS/v2.0/source/COPY.ASM
2018-09-21 17:53:34 -07:00

579 lines
20 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

TITLE COMMAND COPY routines.
INCLUDE COMSW.ASM
.xlist
.xcref
INCLUDE DOSSYM.ASM
INCLUDE DEVSYM.ASM
INCLUDE COMSEG.ASM
.list
.cref
INCLUDE COMEQU.ASM
DATARES SEGMENT PUBLIC
EXTRN VERVAL:WORD
DATARES ENDS
TRANDATA SEGMENT PUBLIC
EXTRN BADARGS:BYTE,BADCD:BYTE,BADSWT:BYTE,COPIED_PRE:BYTE
EXTRN COPIED_POST:BYTE
EXTRN INBDEV:BYTE,OVERWR:BYTE,FULDIR:BYTE,LOSTERR:BYTE
EXTRN NOSPACE:BYTE,DEVWMES:BYTE,NOTFND:BYTE
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC
EXTRN MELCOPY:BYTE,SRCPT:WORD,MELSTART:WORD,SCANBUF:BYTE
EXTRN DESTFCB2:BYTE,SDIRBUF:BYTE,SRCTAIL:WORD,CFLAG:BYTE
EXTRN NXTADD:WORD,DESTCLOSED:BYTE,ALLSWITCH:WORD,ARGC:BYTE
EXTRN PLUS:BYTE,BINARY:BYTE,ASCII:BYTE,FILECNT:WORD
EXTRN WRITTEN:BYTE,CONCAT:BYTE,DESTBUF:BYTE,SRCBUF:BYTE
EXTRN SDIRBUF:BYTE,DIRBUF:BYTE,DESTFCB:BYTE,FRSTSRCH:BYTE
EXTRN FIRSTDEST:BYTE,DESTISDIR:BYTE,DESTSWITCH:WORD,STARTEL:WORD
EXTRN DESTTAIL:WORD,DESTSIZ:BYTE,DESTINFO:BYTE,INEXACT:BYTE
EXTRN CURDRV:BYTE,DESTVARS:BYTE,RESSEG:WORD,SRCSIZ:BYTE
EXTRN SRCINFO:BYTE,SRCVARS:BYTE,USERDIR1:BYTE,NOWRITE:BYTE
EXTRN RDEOF:BYTE,SRCHAND:WORD,CPDATE:WORD,CPTIME:WORD
EXTRN SRCISDEV:BYTE,BYTCNT:WORD,TPA:WORD,TERMREAD:BYTE
EXTRN DESTHAND:WORD,DESTISDEV:BYTE,DIRCHAR:BYTE
TRANSPACE ENDS
; **************************************************
; COPY CODE
;
TRANCODE SEGMENT PUBLIC BYTE
EXTRN RESTUDIR:NEAR,CERROR:NEAR,SWITCH:NEAR,DISP32BITS:NEAR
EXTRN PRINT:NEAR,TCOMMAND:NEAR,ZPRINT:NEAR,ONESPC:NEAR
EXTRN RESTUDIR1:NEAR,FCB_TO_ASCZ:NEAR,CRLF2:NEAR,SAVUDIR1:NEAR
EXTRN SETREST1:NEAR,BADCDERR:NEAR,STRCOMP:NEAR,DELIM:NEAR
EXTRN UPCONV:NEAR,PATHCHRCMP:NEAR,SCANOFF:NEAR
EXTRN CPARSE:NEAR
EXTRN SEARCH:NEAR,SEARCHNEXT:NEAR,DOCOPY:NEAR,CLOSEDEST:NEAR
EXTRN FLSHFIL:NEAR,SETASC:NEAR,BUILDNAME:NEAR,COPERR:NEAR
PUBLIC COPY,BUILDPATH,COMPNAME,ENDCOPY
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING
DOMELCOPY:
cmp [MELCOPY],0FFH
jz CONTMEL
mov SI,[SRCPT]
mov [MELSTART],si
mov [MELCOPY],0FFH
CONTMEL:
xor BP,BP
mov si,[SRCPT]
mov bl,'+'
SCANSRC2:
mov di,OFFSET TRANGROUP:SCANBUF
call CPARSE
test bh,80H
jz NEXTMEL ; Go back to start
test bh,1 ; Switch ?
jnz SCANSRC2 ; Yes
call SOURCEPROC
call RESTUDIR1
mov di,OFFSET TRANGROUP:DESTFCB2
mov ax,PARSE_FILE_DESCRIPTOR SHL 8
INT int_command
mov bx,OFFSET TRANGROUP:SDIRBUF + 1
mov si,OFFSET TRANGROUP:DESTFCB2 + 1
mov di,[SRCTAIL]
call BUILDNAME
jmp MELDO
NEXTMEL:
call CLOSEDEST
xor ax,ax
mov [CFLAG],al
mov [NXTADD],ax
mov [DESTCLOSED],al
mov si,[MELSTART]
mov [SRCPT],si
call SEARCHNEXT
jz SETNMELJ
jmp ENDCOPY2
SETNMELJ:
jmp SETNMEL
COPY:
; First order of buisness is to find out about the destination
ASSUME DS:TRANGROUP,ES:TRANGROUP
xor ax,ax
mov [ALLSWITCH],AX ; no switches
mov [ARGC],al ; no arguments
mov [PLUS],al ; no concatination
mov [BINARY],al ; Binary not specifically specified
mov [ASCII],al ; ASCII not specifically specified
mov [FILECNT],ax ; No files yet
mov [WRITTEN],al ; Nothing written yet
mov [CONCAT],al ; No concatination
mov [MELCOPY],al ; Not a Mel Hallerman copy
mov word ptr [SCANBUF],ax ; Init buffer
mov word ptr [DESTBUF],ax ; Init buffer
mov word ptr [SRCBUF],ax ; Init buffer
mov word ptr [SDIRBUF],ax ; Init buffer
mov word ptr [DIRBUF],ax ; Init buffer
mov word ptr [DESTFCB],ax ; Init buffer
dec ax
mov [FRSTSRCH],al ; First search call
mov [FIRSTDEST],al ; First time
mov [DESTISDIR],al ; Don't know about dest
mov si,81H
mov bl,'+' ; include '+' as a delimiter
DESTSCAN:
xor bp,bp ; no switches
mov di,offset trangroup:SCANBUF
call CPARSE
PUSHF ; save flags
test bh,80H ; A '+' argument?
jz NOPLUS ; no
mov [PLUS],1 ; yes
NOPLUS:
POPF ; get flags back
jc CHECKDONE ; Hit CR?
test bh,1 ; Switch?
jz TESTP2 ; no
or [DESTSWITCH],BP ; Yes, assume destination
or [ALLSWITCH],BP ; keep tabs on all switches
jmp short DESTSCAN
TESTP2:
test bh,80H ; Plus?
jnz GOTPLUS ; Yes, not a separate arg
inc [ARGC] ; found a real arg
GOTPLUS:
push SI
mov ax,[STARTEL]
mov SI,offset trangroup:SCANBUF ; Adjust to copy
sub ax,SI
mov DI,offset trangroup:DESTBUF
add ax,DI
mov [DESTTAIL],AX
mov [DESTSIZ],cl ; Save its size
inc cx ; Include the NUL
rep movsb ; Save potential destination
mov [DESTINFO],bh ; Save info about it
mov [DESTSWITCH],0 ; reset switches
pop SI
jmp short DESTSCAN ; keep going
CHECKDONE:
mov al,[PLUS]
mov [CONCAT],al ; PLUS -> Concatination
shl al,1
shl al,1
mov [INEXACT],al ; CONCAT -> inexact copy
mov dx,offset trangroup:BADARGS
mov al,[ARGC]
or al,al ; Good number of args?
jz CERROR4J ; no, not enough
cmp al,2
jbe ACOUNTOK
CERROR4J:
jmp CERROR ; no, too many
ACOUNTOK:
mov bp,offset trangroup:DESTVARS
cmp al,1
jnz GOT2ARGS
mov al,[CURDRV] ; Dest is default drive:*.*
add al,'A'
mov ah,':'
mov [bp.SIZ],2
mov di,offset trangroup:DESTBUF
stosw
mov [DESTSWITCH],0 ; no switches on dest
mov [bp.INFO],2 ; Flag dest is ambig
mov [bp.ISDIR],0 ; Know destination specs file
call SETSTARS
GOT2ARGS:
cmp [bp.SIZ],2
jnz NOTSHORTDEST
cmp [DESTBUF+1],':'
jnz NOTSHORTDEST ; Two char file name
or [bp.INFO],2 ; Know dest is d:
mov di,offset trangroup:DESTBUF + 2
mov [bp.ISDIR],0 ; Know destination specs file
call SETSTARS
NOTSHORTDEST:
mov di,[bp.TTAIL]
cmp byte ptr [DI],0
jnz CHKSWTCHES
mov dx,offset trangroup:BADCD
cmp byte ptr [DI-2],':'
jnz CERROR4J ; Trailing '/' error
mov [bp.ISDIR],2 ; Know destination is d:/
or [bp.INFO],6
call SETSTARS
CHKSWTCHES:
mov dx,offset trangroup:BADSWT
mov ax,[ALLSWITCH]
cmp ax,GOTSWITCH
jz CERROR4J ; Switch specified which is not known
; Now know most of the information needed about the destination
TEST AX,VSWITCH ; Verify requested?
JZ NOVERIF ; No
MOV AH,GET_VERIFY_ON_WRITE
INT int_command ; Get current setting
PUSH DS
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
XOR AH,AH
MOV [VERVAL],AX ; Save current setting
POP DS
ASSUME DS:TRANGROUP
MOV AX,(SET_VERIFY_ON_WRITE SHL 8) OR 1 ; Set verify
INT int_command
NOVERIF:
xor bp,bp ; no switches
mov si,81H
mov bl,'+' ; include '+' as a delimiter
SCANFSRC:
mov di,offset trangroup:SCANBUF
call CPARSE ; Parse first source name
test bh,1 ; Switch?
jnz SCANFSRC ; Yes, try again
or [DESTSWITCH],bp ; Include copy wide switches on DEST
test bp,BSWITCH
jnz NOSETCASC ; Binary explicit
cmp [CONCAT],0
JZ NOSETCASC ; Not Concat
mov [ASCII],ASWITCH ; Concat -> ASCII copy if no B switch
NOSETCASC:
push SI
mov ax,[STARTEL]
mov SI,offset trangroup:SCANBUF ; Adjust to copy
sub ax,SI
mov DI,offset trangroup:SRCBUF
add ax,DI
mov [SRCTAIL],AX
mov [SRCSIZ],cl ; Save its size
inc cx ; Include the NUL
rep movsb ; Save this source
mov [SRCINFO],bh ; Save info about it
pop SI
mov ax,bp ; Switches so far
call SETASC ; Set A,B switches accordingly
call SWITCH ; Get any more switches on this arg
call SETASC ; Set
call FRSTSRC
jmp FIRSTENT
ENDCOPY:
CALL CLOSEDEST
ENDCOPY2:
MOV DX,OFFSET TRANGROUP:COPIED_PRE
CALL PRINT
MOV SI,[FILECNT]
XOR DI,DI
CALL DISP32BITS
MOV DX,OFFSET TRANGROUP:COPIED_POST
CALL PRINT
JMP TCOMMAND ; Stack could be messed up
SRCNONEXIST:
cmp [CONCAT],0
jnz NEXTSRC ; If in concat mode, ignore error
mov dx,offset trangroup:SRCBUF
call zprint
CALL ONESPC
mov dx,offset trangroup:NOTFND
jmp COPERR
SOURCEPROC:
push SI
mov ax,[STARTEL]
mov SI,offset trangroup:SCANBUF ; Adjust to copy
sub ax,SI
mov DI,offset trangroup:SRCBUF
add ax,DI
mov [SRCTAIL],AX
mov [SRCSIZ],cl ; Save its size
inc cx ; Include the NUL
rep movsb ; Save this sorce
mov [SRCINFO],bh ; Save info about it
pop SI
mov ax,bp ; Switches so far
call SETASC ; Set A,B switches accordingly
call SWITCH ; Get any more switches on this arg
call SETASC ; Set
cmp [CONCAT],0
jnz LEAVECFLAG ; Leave CFLAG if concatination
FRSTSRC:
xor ax,ax
mov [CFLAG],al ; Flag destination not created
mov [NXTADD],ax ; Zero out buffer
mov [DESTCLOSED],al ; Not created -> not closed
LEAVECFLAG:
mov [SRCPT],SI ; remember where we are
mov di,offset trangroup:USERDIR1
mov bp,offset trangroup:SRCVARS
call BUILDPATH ; Figure out everything about the source
mov si,[SRCTAIL] ; Create the search FCB
return
NEXTSRC:
cmp [PLUS],0
jnz MORECP
ENDCOPYJ2:
jmp ENDCOPY ; Done
MORECP:
xor bp,bp ; no switches
mov si,[SRCPT]
mov bl,'+' ; include '+' as a delimiter
SCANSRC:
mov di,offset trangroup:SCANBUF
call CPARSE ; Parse first source name
JC EndCopyJ2 ; if error, then end (trailing + case)
test bh,80H
jz ENDCOPYJ2 ; If no '+' we're done
test bh,1 ; Switch?
jnz SCANSRC ; Yes, try again
call SOURCEPROC
FIRSTENT:
mov di,FCB
mov ax,PARSE_FILE_DESCRIPTOR SHL 8
INT int_command
mov ax,word ptr [SRCBUF] ; Get drive
cmp ah,':'
jz DRVSPEC1
mov al,'@'
DRVSPEC1:
sub al,'@'
mov ds:[FCB],al
mov ah,DIR_SEARCH_FIRST
call SEARCH
pushf ; Save result of search
call RESTUDIR1 ; Restore users dir
popf
jz NEXTAMBIG0
jmp SRCNONEXIST ; Failed
NEXTAMBIG0:
xor al,al
xchg al,[FRSTSRCH]
or al,al
jz NEXTAMBIG
SETNMEL:
mov cx,12
mov di,OFFSET TRANGROUP:SDIRBUF
mov si,OFFSET TRANGROUP:DIRBUF
rep movsb ; Save very first source name
NEXTAMBIG:
xor al,al
mov [NOWRITE],al ; Turn off NOWRITE
mov di,[SRCTAIL]
mov si,offset trangroup:DIRBUF + 1
call FCB_TO_ASCZ ; SRCBUF has complete name
MELDO:
cmp [CONCAT],0
jnz SHOWCPNAM ; Show name if concat
test [SRCINFO],2 ; Show name if multi
jz DOREAD
SHOWCPNAM:
mov dx,offset trangroup:SRCBUF
call ZPRINT
call CRLF2
DOREAD:
call DOCOPY
cmp [CONCAT],0
jnz NODCLOSE ; If concat, do not close
call CLOSEDEST ; else close current destination
jc NODCLOSE ; Concat flag got set, close didn't really happen
mov [CFLAG],0 ; Flag destination not created
NODCLOSE:
cmp [CONCAT],0 ; Check CONCAT again
jz NOFLUSH
CALL FLSHFIL ; Flush output between source files on CONCAT
; so LOSTERR stuff works correctly
TEST [MELCOPY],0FFH
jz NOFLUSH
jmp DOMELCOPY
NOFLUSH:
call SEARCHNEXT ; Try next match
jnz NEXTSRCJ ; Finished with this source spec
mov [DESTCLOSED],0 ; Not created or concat -> not closed
jmp NEXTAMBIG ; Do next ambig
NEXTSRCJ:
jmp NEXTSRC
BUILDPATH:
test [BP.INFO],2
jnz NOTPFILE ; If ambig don't bother with open
mov dx,bp
add dx,BUF ; Set DX to spec
mov ax,OPEN SHL 8
INT int_command
jc NOTPFILE
mov bx,ax ; Is pure file
mov ax,IOCTL SHL 8
INT int_command
mov ah,CLOSE
INT int_command
test dl,devid_ISDEV
jnz ISADEV ; If device, done
test [BP.INFO],4
jz ISSIMPFILE ; If no path seps, done
NOTPFILE:
mov dx,word ptr [BP.BUF]
cmp dh,':'
jz DRVSPEC5
mov dl,'@'
DRVSPEC5:
sub dl,'@' ; A = 1
call SAVUDIR1
mov dx,bp
add dx,BUF ; Set DX for upcomming CHDIRs
mov bh,[BP.INFO]
and bh,6
cmp bh,6 ; Ambig and path ?
jnz CHECKAMB ; jmp if no
mov si,[BP.TTAIL]
cmp byte ptr [si-2],':'
jnz KNOWNOTSPEC
mov [BP.ISDIR],2 ; Know is d:/file
jmp short DOPCDJ
KNOWNOTSPEC:
mov [BP.ISDIR],1 ; Know is path/file
dec si ; Point to the /
DOPCDJ:
jmp short DOPCD
CHECKAMB:
cmp bh,2
jnz CHECKCD
ISSIMPFILE:
ISADEV:
mov [BP.ISDIR],0 ; Know is file since ambig but no path
return
CHECKCD:
call SETREST1
mov ah,CHDIR
INT int_command
jc NOTPDIR
mov di,dx
xor ax,ax
mov cx,ax
dec cx
repne scasb
dec di
mov al,[DIRCHAR]
mov [bp.ISDIR],2 ; assume d:/file
cmp al,[di-1]
jz GOTSRCSLSH
stosb
mov [bp.ISDIR],1 ; know path/file
GOTSRCSLSH:
or [bp.INFO],6
call SETSTARS
return
NOTPDIR:
mov [bp.ISDIR],0 ; assume pure file
mov bh,[bp.INFO]
test bh,4
retz ; Know pure file, no path seps
mov [bp.ISDIR],2 ; assume d:/file
mov si,[bp.TTAIL]
cmp byte ptr [si],0
jz BADCDERRJ2 ; Trailing '/'
cmp byte ptr [si],'.'
jz BADCDERRJ2 ; If . or .. pure cd should have worked
cmp byte ptr [si-2],':'
jz DOPCD ; Know d:/file
mov [bp.ISDIR],1 ; Know path/file
dec si ; Point at last '/'
DOPCD:
xor bl,bl
xchg bl,[SI] ; Stick in a NUL
call SETREST1
mov ah,CHDIR
INT int_command
xchg bl,[SI]
retnc
BADCDERRJ2:
JMP BADCDERR
SETSTARS:
mov [bp.TTAIL],DI
add [bp.SIZ],12
mov ax,('.' SHL 8) OR '?'
mov cx,8
rep stosb
xchg al,ah
stosb
xchg al,ah
mov cl,3
rep stosb
xor al,al
stosb
return
COMPNAME:
PUSH CX
PUSH AX
MOV si,offset trangroup:SRCBUF
MOV di,offset trangroup:DESTBUF
MOV CL,[CURDRV]
MOV CH,CL
CMP BYTE PTR [SI+1],':'
JNZ NOSRCDRV
LODSW
SUB AL,'A'
MOV CL,AL
NOSRCDRV:
CMP BYTE PTR [DI+1],':'
JNZ NODSTDRV
MOV AL,[DI]
INC DI
INC DI
SUB AL,'A'
MOV CH,AL
NODSTDRV:
CMP CH,CL
jnz RET81P
call STRCOMP
jz RET81P
mov ax,[si-1]
mov cx,[di-1]
push ax
and al,cl
pop ax
jnz RET81P ; Niether of the mismatch chars was a NUL
; Know one of the mismatch chars is a NUL
; Check for ".NUL" compared with NUL
cmp al,'.'
jnz CHECKCL
or ah,ah
jmp short RET81P ; If NUL return match, else no match
CHECKCL:
cmp cl,'.'
jnz RET81P ; Mismatch
or ch,ch ; If NUL return match, else no match
RET81P:
POP AX
POP CX
return
TRANCODE ENDS
END