MS-DOS/v2.0/source/EDLIN.ASM

1846 lines
54 KiB
NASM
Raw Normal View History

1983-08-13 01:53:34 +01:00
title EDLIN for MSDOS 2.0
;-----------------------------------------------------------------------;
; REVISION HISTORY: ;
; ;
; V1.02 ;
; ;
; V2.00 9/13/82 M.A. Ulloa ;
; Modified to use Pathnames in command line file ;
; specification, modified REPLACE to use an empty ;
; string intead of the old replace string when this ;
; is missing, and search and replace now start from ;
; first line of buffer (like old version of EDLIN) ;
; instead than current+1 line. Also added the U and ;
; V commands that search (replace) starting from the ;
; current+1 line. ;
; ;
; 9/15/82 M.A. Ulloa ;
; Added the quote character (^V). ;
; ;
; 9/16/82 M.A. Ulloa ;
; Corrected bug about use of quote char when going ;
; into default insert mode. Also corrected the problem ;
; with ^Z being the end of file marker. End of file is ;
; reached when an attempt to read returns less chars ;
; than requested. ;
; ;
; 9/17/82 M.A. Ulloa ;
; Corrected bug about boundaries for Copy ;
; ;
; 10/4/82 Rev. 1 M.A. Ulloa ;
; The IBM version now does NOT have the U and V ;
; commands. The MSDOS version HAS the U and V commands. ;
; Added the B switch, and modified the effect of ;
; the quote char. ;
; ;
; 10/7/82 Rev. 2 M.A. Ulloa ;
; Changed the S and R commands to start from the ;
; current line+1 (as U and V did). Took away U and V in ;
; all versions. ;
; ;
; 10/13/82 Rev. 3 M.A. Ulloa ;
; Now if parameter1 < 1 then parameter1 = 1 ;
; ;
; 10/15/82 Rev. 4 M.A. Ulloa ;
; Param4 if specified must be an absolute number that ;
; reprecents the count. ;
; ;
; 10/18/82 Rev. 5 M.A. Ulloa ;
; Fixed problem with trying to edit files with the ;
; same name as directories. Also, if the end of file is ;
; reached it checks that a LF is the last character, ;
; otherwise it inserts a CRLF pair at the end. ;
; ;
; 10/20/82 Rev. 6 M.A.Ulloa ;
; Changed the text of some error messages for IBM and ;
; rewrite PAGE. ;
; ;
; 10/25/82 Rev. 7 M.A.Ulloa ;
; Made all messages as in the IBM vers. ;
; ;
; 10/28/82 Rev. 8 M.A.Ulloa ;
; Corrected problem with parsing for options. ;
; ;
; Rev. 9 Aaron Reynolds ;
; Made error messages external. ;
; ;
; 12/08/82 Rev. 10 M.A. Ulloa ;
; Corrected problem arising with having to restore ;
; the old directory in case of a file name error. ;
; ;
; 12/17/82 Rev. 11 M.A. Ulloa ;
; Added the ROPROT equate for R/O file protection. ;
; It causes only certain operations (L,P,S,W,A, and Q) ;
; to be allowed on read only files. ;
; ;
; 12/29/82 Rev. 12 M.A. Ulloa :
; Added the creation error message. ;
; ;
; 4/14/83 Rev. 13 N.Panners ;
; Fixed bug in Merge which lost char if not ^Z. ;
; Fixed bug in Copy to correctly check ;
; for full buffers. ;
; ;
; ;
; 7/23/83 Rev. 14 N.Panners ;
; Split EDLIN into two seperate modules to ;
; allow assembly of sources on an IBM PC ;
; EDLIN and EDLPROC ;
; ;
;-----------------------------------------------------------------------;
FALSE EQU 0
TRUE EQU NOT FALSE
KANJI EQU FALSE
roprot equ true ;set to TRUE if protection to r/o files
; desired.
FCB EQU 5CH
Comand_Line_Length equ 128
quote_char equ 16h ;quote character = ^V
PAGE
.xlist
INCLUDE DOSSYM.ASM
.list
SUBTTL Contants and Data areas
PAGE
PROMPT EQU "*"
STKSIZ EQU 80H
CODE SEGMENT PUBLIC
CODE ENDS
CONST SEGMENT PUBLIC WORD
CONST ENDS
DATA SEGMENT PUBLIC WORD
DATA ENDS
DG GROUP CODE,CONST,DATA
CONST SEGMENT PUBLIC WORD
EXTRN BADDRV:BYTE,NDNAME:BYTE,bad_vers_err:BYTE,opt_err:BYTE
EXTRN NOBAK:BYTE,BADCOM:BYTE,NEWFIL:BYTE,DEST:BYTE,MRGERR:BYTE
EXTRN NODIR:BYTE,DSKFUL:BYTE,MEMFUL:BYTE,FILENM:BYTE
EXTRN NOSUCH:BYTE,TOOLNG:BYTE,EOF:BYTE,ro_err:byte,bcreat:byte
PUBLIC TXT1,TXT2,FUDGE,USERDIR,HARDCH
BAK DB "BAK"
make db "***MAUlloa/Microsoft/V20***"
rev db "14"
if roprot ;***** R/O *****
roflag db 0 ; =1 if file is r/o
endif
fourth db 0 ;fourth parameter flag
loadmod db 0 ;Load mode flag, 0 = ^Z marks the
; end of a file, 1 = viceversa.
hardch dd ?
the_root db 0 ;root directory flag
fudge db 0 ;directory changed flag
user_drive db 0
optchar db "-"
dirchar db "/",0
userdir db "/",0
db (dirstrlen) dup(0)
fname_buffer db Comand_Line_Length dup(0)
;-----------------------------------------------------------------------;
TXT1 DB 0,80H DUP (?)
TXT2 DB 0,80H DUP (?)
DELFLG DB 0
CONST ENDS
DATA SEGMENT PUBLIC WORD
PUBLIC QFLG,FCB2,OLDLEN,PARAM1,PARAM2,OLDDAT,SRCHFLG
PUBLIC COMLINE,NEWLEN,SRCHMOD,CURRENT,LSTFND,NUMPOS
PUBLIC LSTNUM,SRCHCNT,POINTER,START,ENDTXT,USER_DRIVE
;-----------------------------------------------------------------------;
; Be carefull when adding parameters, they have to follow the
; order in which they apperar here. (this is a table, ergo it
; is indexed thru a pointer, and random additions will cause the
; wrong item to be accessed). Also param4 is known to be the
; count parameter, and known to be the fourth entry in the table
; so it receives special treatment. (See GETNUM)
PARAM1 DW 1 DUP (?)
PARAM2 DW 1 DUP (?)
PARAM3 DW 1 DUP (?)
PARAM4 DW 1 DUP (?)
;-----------------------------------------------------------------------;
PTR_1 DW 1 DUP (?)
PTR_2 DW 1 DUP (?)
PTR_3 DW 1 DUP (?)
COPYSIZ DW 1 DUP (?)
OLDLEN DW 1 DUP (?)
NEWLEN DW 1 DUP (?)
LSTFND DW 1 DUP (?)
LSTNUM DW 1 DUP (?)
NUMPOS DW 1 DUP (?)
SRCHCNT DW 1 DUP (?)
CURRENT DW 1 DUP (?)
POINTER DW 1 DUP (?)
ONE4TH DW 1 DUP (?)
THREE4TH DW 1 DUP (?)
LAST DW 1 DUP (?)
ENDTXT DW 1 DUP (?)
COMLINE DW 1 DUP (?)
LASTLIN DW 1 DUP (?)
COMBUF DB 82H DUP (?)
EDITBUF DB 258 DUP (?)
EOL DB 1 DUP (?)
FCB2 DB 37 DUP (?)
FCB3 DB 37 DUP (?)
fake_fcb db 37 dup (?) ;fake for size figuring
QFLG DB 1 DUP (?)
HAVEOF DB 1 DUP (?)
ENDING DB 1 DUP (?)
SRCHFLG DB 1 DUP (?)
amnt_req dw 1 dup (?) ;ammount of bytes requested to read
olddat db 1 dup (?) ;Used in replace and search,
; replace by old data flag (1=yes)
srchmod db 1 dup (?) ;Search mode: 1=from current+1 to
; end of buffer, 0=from beg. of
; buffer to the end (old way).
MOVFLG DB 1 DUP (?)
DB STKSIZ DUP (?)
STACK LABEL BYTE
START LABEL WORD
DATA ENDS
SUBTTL Main Body
PAGE
CODE SEGMENT PUBLIC
ASSUME CS:DG,DS:DG,SS:DG,ES:DG
EXTRN QUIT:NEAR,QUERY:NEAR,FNDFIRST:NEAR,FNDNEXT:NEAR
EXTRN UNQUOTE:NEAR,LF:NEAR,CRLF:NEAR,OUT:NEAR
EXTRN REST_DIR:NEAR,KILL_BL:NEAR,INT_24:NEAR
EXTRN FINDLIN:NEAR,SHOWNUM:NEAR,SCANLN:NEAR
if Kanji
EXTRN TESTKANJ:NEAR
endif
PUBLIC CHKRANGE
ORG 100H
EDLIN:
JMP SIMPED
edl_pad db 0e00h dup (?)
HEADER DB "Vers 2.14"
NONAME:
MOV DX,OFFSET DG:NDNAME
ERRJ: JMP xERROR
SIMPED:
MOV BYTE PTR [ENDING],0
MOV SP,OFFSET DG:STACK
;Code to print header
; PUSH AX
; MOV DX,OFFSET DG:HEADER
; MOV AH,STD_CON_STRING_OUTPUT
; INT 21H
; POP AX
;----- Check Version Number --------------------------------------------;
push ax
mov ah,Get_Version
int 21h
cmp al,2
jae vers_ok ; version >= 2, enter editor
mov dx,offset dg:bad_vers_err
jmp short errj
;-----------------------------------------------------------------------;
vers_ok:
;----- Process Pathnames -----------------------------------------------;
mov ax,(char_oper shl 8) ;get switch character
int 21h
cmp dl,"/"
jnz slashok ;if not / , then not PC
mov [dirchar],"\" ;in PC, dir separator = \
mov [userdir],"\"
mov [optchar],"/" ;in PC, option char = /
slashok:
mov si,81h ;point to cammand line
call kill_bl
cmp al,13 ;A carriage return?
je noname ;yes, file name missing
mov di,offset dg:fname_buffer
xor cx,cx ;zero pathname length
next_char:
stosb ;put patname in buffer
inc cx
lodsb
cmp al,' '
je xx1
cmp al,13 ; a CR ?
je name_copied
cmp al,[optchar] ; an option character?
je an_option
jmp short next_char
xx1:
dec si
call kill_bl
cmp al,[optchar]
jne name_copied
an_option:
lodsb ;get the option
cmp al,'B'
je b_opt
cmp al,'b'
je b_opt
mov dx,offset dg:opt_err ;bad option specified
jmp xerror
b_opt:
mov [loadmod],1
name_copied:
mov byte ptr dg:[di],0 ;nul terminate the pathname
if roprot ;***** R/O *****
;----- Check that file is not R/O --------------------------------------;
push cx ;save character count
mov dx,offset dg:fname_buffer
mov al,0 ;get attributes
mov ah,chmod
int 21h
jc attr_are_ok
and cl,00000001b ;mask all but: r/o
jz attr_are_ok ;if all = 0 then file ok to edit,
mov dg:[roflag],01h ;otherwise: Error (GONG!!!)
attr_are_ok:
pop cx ;restore character count
endif
;----- Scan for directory ----------------------------------------------;
dec di ;adjust to the end of the pathname
IF KANJI
mov dx,offset dg: fname_buffer
PUSH DX
PUSH DI
MOV BX,DI
MOV DI,DX
DELLOOP:
CMP DI,BX
Jae GOTDELE
MOV AL,[DI]
INC DI
CALL TESTKANJ
JZ NOTKANJ11
INC DI
JMP DELLOOP
NOTKANJ11:
cmp al,dg:[dirchar]
JNZ DELLOOP
MOV DX,DI ;Point to char after '/'
DEC DX
DEC DX ;Point to char before '/'
JMP DELLOOP
GOTDELE:
MOV DI,DX
POP AX ;Initial DI
POP DX
SUB AX,DI ;Distance moved
SUB CX,AX ;Set correct CX
CMP DX,DI
JB sj1 ;Found a pathsep
JA sj2 ;Started with a pathsep, root
MOV AX,[DI]
CALL TESTKANJ
JNZ same_dirj
XCHG AH,AL
cmp al,dg:[dirchar]
jz sj1 ;One character directory
same_dirj:
ELSE
mov al,dg:[dirchar] ;get directory separator character
std ;scan backwards
repnz scasb ;(cx has the pathname length)
cld ;reset direction, just in case
jz sj1
ENDIF
jmp same_dir ;no dir separator char. found, the
; file is in the current directory
; of the corresponding drive. Ergo,
; the FCB contains the data already.
sj1:
jcxz sj2 ;no more chars left, it refers to root
cmp byte ptr [di],':' ;is the prvious character a disk def?
jne not_root
sj2:
mov dg:[the_root],01h ;file is in the root
not_root:
inc di ;point to dir separator char.
mov al,0
stosb ;nul terminate directory name
pop ax
push di ;save pointer to file name
mov dg:[fudge],01h ;remember that the current directory
; has been changed.
;----- Save current directory for exit ---------------------------------;
mov ah,get_default_drive ;save current drive
int 21h
mov dg:[user_drive],al
mov dl,byte ptr ds:[fcb] ;get specified drive if any
or dl,dl ;default disk?
jz same_drive
dec dl ;adjust to real drive (a=0,b=1,...)
mov ah,set_default_drive ;change disks
int 21h
cmp al,-1 ;error?
jne same_drive
mov dx,offset dg:baddrv
jmp xerror
same_drive:
mov ah,get_default_dpb
int 21h
assume ds:nothing
cmp al,-1 ;bad drive? (should always be ok)
jne drvisok
mov dx,offset dg:baddrv
jmp xerror
drvisok:
cmp [bx.dpb_current_dir],0
je curr_is_root
mov si,bx
add si,dpb_dir_text
mov di,offset dg:userdir + 1
dir_save_loop:
lodsb
stosb
or al,al
jnz dir_save_loop
curr_is_root:
push cs
pop ds
assume ds:dg
;----- Change directories ----------------------------------------------;
cmp [the_root],01h
mov dx,offset dg:[dirchar] ;assume the root
je sj3
mov dx,offset dg:[fname_buffer]
sj3:
mov ah,chdir ;change directory
int 21h
mov dx,offset dg:baddrv
jnc no_errors
jmp xerror
no_errors:
;----- Set Up int 24 intercept -----------------------------------------;
mov ax,(get_interrupt_vector shl 8) or 24h
int 21h
mov word ptr [hardch],bx
mov word ptr [hardch+2],es
mov ax,(set_interrupt_vector shl 8) or 24h
mov dx,offset dg:int_24
int 21h
push cs
pop es
;----- Parse filename to FCB -------------------------------------------;
pop si
mov di,fcb
mov ax,(parse_file_descriptor shl 8) or 1
int 21h
push ax
;-----------------------------------------------------------------------;
same_dir:
pop ax
OR AL,AL
MOV DX,OFFSET DG:BADDRV
jz sj4
jmp xerror
sj4:
CMP BYTE PTR DS:[FCB+1]," "
jnz sj5
jmp noname
sj5:
MOV SI,OFFSET DG:BAK
MOV DI,FCB+9
MOV CX,3
;File must not have .BAK extension
REPE CMPSB
JZ NOTBAK
;Open input file
MOV AH,FCB_OPEN
MOV DX,FCB
INT 21H
MOV [HAVEOF],AL
OR AL,AL
JZ HAVFIL
;----- Check that file is not a directory ------------
mov ah,fcb_create
mov dx,fcb
int 21h
or al,al
jz sj50 ;no error found
mov dx,offset dg:bcreat ;creation error
jmp xerror
sj50:
mov ah,fcb_close ;no error, close the file
mov dx,fcb
int 21h
mov ah,fcb_delete ;delete the file
mov dx,fcb
int 21h
;-----------------------------------------------------
MOV DX,OFFSET DG:NEWFIL
MOV AH,STD_CON_STRING_OUTPUT
INT 21H
HAVFIL:
MOV SI,FCB
MOV DI,OFFSET DG:FCB2
MOV CX,9
REP MOVSB
MOV AL,"$"
STOSB
STOSB
STOSB
MAKFIL:
;Create .$$$ file to make sure directory has room
MOV DX,OFFSET DG:FCB2
MOV AH,FCB_CREATE
INT 21H
OR AL,AL
JZ SETUP
CMP BYTE PTR [DELFLG],0
JNZ NOROOM
CALL DELBAK
JMP MAKFIL
NOROOM:
MOV DX,OFFSET DG:NODIR
JMP xERROR
NOTBAK:
MOV DX,OFFSET DG:NOBAK
JMP xERROR
SETUP:
XOR AX,AX
MOV WORD PTR DS:[FCB+fcb_RR],AX ;Set RR field to zero
MOV WORD PTR DS:[FCB+fcb_RR+2],AX
MOV WORD PTR [FCB2+fcb_RR],AX
MOV WORD PTR [FCB2+fcb_RR+2],AX
INC AX
MOV WORD PTR DS:[FCB+fcb_RECSIZ],AX ;Set record length to 1
MOV WORD PTR [FCB2+fcb_RECSIZ],AX
MOV DX,OFFSET DG:START
MOV DI,DX
MOV AH,SET_DMA
INT 21H
MOV CX,DS:[6]
DEC CX
MOV [LAST],CX
TEST BYTE PTR [HAVEOF],-1
JNZ SAVEND
SUB CX,OFFSET DG:START ;Available memory
SHR CX,1 ;1/2 of available memory
MOV AX,CX
SHR CX,1 ;1/4 of available memory
MOV [ONE4TH],CX ;Save amount of 1/4 full
ADD CX,AX ;3/4 of available memory
MOV DX,CX
ADD DX,OFFSET DG:START
MOV [THREE4TH],DX ;Save pointer to 3/4 full
;Read in input file
MOV DX,FCB
MOV AH,FCB_RANDOM_READ_BLOCK
mov [amnt_req],cx ;save ammount of chars requested
INT 21H
CALL SCANEOF
ADD DI,CX ;Point to last byte
SAVEND:
CLD
MOV BYTE PTR [DI],1AH
MOV [ENDTXT],DI
MOV BYTE PTR [COMBUF],128
MOV BYTE PTR [EDITBUF],255
MOV BYTE PTR [EOL],10
MOV [POINTER],OFFSET DG:START
MOV [CURRENT],1
MOV [PARAM1],1
TEST BYTE PTR [HAVEOF],-1
JNZ COMMAND
CALL APPEND
COMMAND:
MOV SP, OFFSET DG:STACK
MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 23H
MOV DX,OFFSET DG:ABORTCOM
INT 21H
MOV AL,PROMPT
CALL OUT
MOV DX,OFFSET DG:COMBUF
MOV AH,STD_CON_STRING_INPUT
INT 21H
MOV [COMLINE],OFFSET DG:COMBUF + 2
MOV AL,10
CALL OUT
PARSE:
MOV [PARAM2],0
MOV [PARAM3],0
MOV [PARAM4],0
mov [fourth],0 ;reset the fourth parameter flag
MOV BYTE PTR [QFLG],0
MOV SI,[COMLINE]
MOV BP,OFFSET DG:PARAM1
XOR DI,DI
CHKLP:
CALL GETNUM
MOV [BP+DI],DX
INC DI
INC DI
CALL SKIP1
CMP AL,","
JNZ CHKNXT
INC SI
CHKNXT:
DEC SI
CMP DI,8
JB CHKLP
CALL SKIP
CMP AL,"?"
JNZ DISPATCH
MOV [QFLG],AL
CALL SKIP
DISPATCH:
CMP AL,5FH
JBE UPCASE
AND AL,5FH
UPCASE:
MOV DI,OFFSET DG:COMTAB
MOV CX,NUMCOM
REPNE SCASB
JNZ COMERR
MOV BX,CX
MOV AX,[PARAM2]
OR AX,AX
JZ PARMOK
CMP AX,[PARAM1]
JB COMERR ;Param. 2 must be >= param 1
PARMOK:
MOV [COMLINE],SI
if roprot ;***** R/O *****
cmp [roflag],01 ;file r/o?
jne paramok2
cmp byte ptr [bx+rotable],01 ;operation allowed?
je paramok2
mov dx,offset dg:ro_err ;error
jmp short comerr1
paramok2:
endif
SHL BX,1
CALL [BX+TABLE]
COMOVER:
MOV SI,[COMLINE]
CALL SKIP
CMP AL,0DH
JZ COMMANDJ
CMP AL,1AH
JZ DELIM
CMP AL,";"
JNZ NODELIM
DELIM:
INC SI
NODELIM:
DEC SI
MOV [COMLINE],SI
JMP PARSE
COMMANDJ:
JMP COMMAND
SKIP:
LODSB
SKIP1:
CMP AL," "
JZ SKIP
RET1: RET
CHKRANGE:
CMP [PARAM2],0
JZ RET1
CMP BX,[PARAM2]
JBE RET1
COMERR:
MOV DX,OFFSET DG:BADCOM
COMERR1:
MOV AH,STD_CON_STRING_OUTPUT
INT 21H
JMP COMMAND
GETNUM:
CALL SKIP
cmp di,6 ;Is this the fourth parameter?
jne sk1
mov [fourth],1 ;yes, set the flag
sk1:
CMP AL,"."
JZ CURLIN
CMP AL,"#"
JZ MAXLIN
CMP AL,"+"
JZ FORLIN
CMP AL,"-"
JZ BACKLIN
MOV DX,0
MOV CL,0 ;Flag no parameter seen yet
NUMLP:
CMP AL,"0"
JB NUMCHK
CMP AL,"9"
JA NUMCHK
CMP DX,6553 ;Max line/10
JAE COMERR ;Ten times this is too big
MOV CL,1 ;Parameter digit has been found
SUB AL,"0"
MOV BX,DX
SHL DX,1
SHL DX,1
ADD DX,BX
SHL DX,1
CBW
ADD DX,AX
LODSB
JMP SHORT NUMLP
NUMCHK:
CMP CL,0
JZ RET1
OR DX,DX
JZ COMERR ;Don't allow zero as a parameter
RET
CURLIN:
cmp [fourth],1 ;the fourth parameter?
je comerra ;yes, an error
MOV DX,[CURRENT]
LODSB
RET
MAXLIN:
cmp [fourth],1 ;the fourth parameter?
je comerra ;yes, an error
MOV DX,-2
LODSB
RET
FORLIN:
cmp [fourth],1 ;the fourth parameter?
je comerra ;yes, an error
CALL GETNUM
ADD DX,[CURRENT]
RET
BACKLIN:
cmp [fourth],1 ;the fourth parameter?
je comerra ;yes, an error
CALL GETNUM
MOV BX,[CURRENT]
SUB BX,DX
jns sk2 ;if below beg of buffer then default to the
mov bx,1 ; beg of buffer (line1)
sk2:
MOV DX,BX
RET
comerra:
jmp comerr
COMTAB DB "QTCMWASRDLPIE;",13
NUMCOM EQU $-COMTAB
;-----------------------------------------------------------------------;
; Carefull changing the order of the next two tables. They are
; linked and chnges should be be to both.
TABLE DW NOCOM ;No command--edit line
DW NOCOM
DW ENDED
DW INSERT
DW PAGE
DW LIST
DW DELETE
dw replac_from_curr ;replace from current+1 line
dw search_from_curr ;search from current+1 line
DW APPEND
DW EWRITE
DW MOVE
DW COPY
DW MERGE
if roprot ;***** R/O *****
DW QUIT1
else
DW QUIT
endif
if roprot ;***** R/O *****
;-----------------------------------------------------------------------;
; If = 1 then the command can be executed with a file that
; is r/o. If = 0 the command can not be executed, and error.
ROTABLE db 0 ;NOCOM
db 0 ;NOCOM
db 0 ;ENDED
db 0 ;INSERT
db 1 ;PAGE
db 1 ;LIST
db 0 ;DELETE
db 0 ;replac_from_curr
db 1 ;search_from_curr
db 1 ;APPEND
db 1 ;EWRITE
db 0 ;MOVE
db 0 ;COPY
db 0 ;MERGE
db 1 ;QUIT
;-----------------------------------------------------------------------;
endif
if roprot ;***** R/O *****
quit1:
cmp [roflag],01 ;are we in r/o mode?
jne q3 ;no query....
MOV DX,OFFSET DG:FCB2 ;yes, quit without query.
MOV AH,FCB_CLOSE
INT 21H
MOV AH,FCB_DELETE
INT 21H
call rest_dir ;restore directory if needed
INT 20H
q3:
call quit
endif
SCANEOF:
cmp [loadmod],0
je sj52
;----- Load till physical end of file
cmp cx,word ptr[amnt_req]
jb sj51
xor al,al
inc al ;reset zero flag
ret
sj51:
jcxz sj51b
push di ;get rid of any ^Z at the end of the file
add di,cx
dec di ;points to last char
cmp byte ptr [di],1ah
pop di
jne sj51b
dec cx
sj51b:
xor al,al ;set zero flag
call check_end ;check that we have a CRLF pair at the end
ret
;----- Load till first ^Z is found
sj52:
PUSH DI
PUSH CX
MOV AL,1AH
or cx,cx
jz not_found ;skip with zero flag set
REPNE SCASB ;Scan for end of file mark
jnz not_found
LAHF ;Save flags momentarily
inc cx ;include the ^Z
SAHF ;Restore flags
not_found:
mov di,cx ;not found at the end
POP CX
LAHF ;Save flags momentarily
SUB CX,DI ;Reduce byte count if EOF found
SAHF ;Restore flags
POP DI
call check_end ;check that we have a CRLF pair at the end
RET2: RET
;-----------------------------------------------------------------------
; If the end of file was found, then check that the last character
; in the file is a LF. If not put a CRLF pair in.
check_end:
jnz not_end ;end was not reached
pushf ;save return flag
push di ;save pointer to buffer
add di,cx ;points to one past end on text
dec di ;points to last character
cmp di,offset dg:start
je check_no
cmp byte ptr[di],0ah ;is a LF the last character?
je check_done ;yes, exit
check_no:
mov byte ptr[di+1],0dh ;no, put a CR
inc cx ;one more char in text
mov byte ptr[di+2],0ah ;put a LF
inc cx ;another character at the end
check_done:
pop di
popf
not_end:
ret
NOMOREJ:JMP NOMORE
APPEND:
TEST BYTE PTR [HAVEOF],-1
JNZ NOMOREJ
MOV DX,[ENDTXT]
CMP [PARAM1],0 ;See if parameter is missing
JNZ PARMAPP
CMP DX,[THREE4TH] ;See if already 3/4ths full
JAE RET2 ;If so, then done already
PARMAPP:
MOV DI,DX
MOV AH,SET_DMA
INT 21H
MOV CX,[LAST]
SUB CX,DX ;Amount of memory available
jnz sj53
jmp memerr
sj53:
MOV DX,FCB
mov [amnt_req],cx ;save ammount of chars requested
MOV AH,FCB_RANDOM_READ_BLOCK
INT 21H ;Fill memory with file data
MOV [HAVEOF],AL
PUSH CX ;Save actual byte count
CALL SCANEOF
JNZ NOTEND
MOV BYTE PTR [HAVEOF],1 ;Set flag if 1AH found in file
NOTEND:
XOR DX,DX
MOV BX,[PARAM1]
OR BX,BX
JNZ COUNTLN
MOV AX,DI
ADD AX,CX ;First byte after loaded text
CMP AX,[THREE4TH] ;See if we made 3/4 full
JBE COUNTLN
MOV DI,[THREE4TH]
MOV CX,AX
SUB CX,DI ;Length remaining over 3/4
MOV BX,1 ;Look for one more line
COUNTLN:
CALL SCANLN ;Look for BX lines
CMP [DI-1],AL ;Check for full line
JZ FULLN
STD
DEC DI
MOV CX,[LAST]
REPNE SCASB ;Scan backwards for last line
INC DI
INC DI
DEC DX
CLD
FULLN:
POP CX ;Actual amount read
MOV WORD PTR [DI],1AH ;Place EOF after last line
SUB CX,DI
XCHG DI,[ENDTXT]
ADD DI,CX ;Amount of file read but not used
SUB WORD PTR DS:[FCB+fcb_RR],DI ;Adjust RR field in case end of file
SBB WORD PTR DS:[FCB+fcb_RR+2],0 ; was not reached
CMP BX,DX
JNZ EOFCHK
MOV BYTE PTR [HAVEOF],0
RET
NOMORE:
MOV DX,OFFSET DG:EOF
MOV AH,STD_CON_STRING_OUTPUT
INT 21H
RET3: RET
EOFCHK:
TEST BYTE PTR [HAVEOF],-1
JNZ NOMORE
TEST BYTE PTR [ENDING],-1
JNZ RET3 ;Suppress memory error during End
JMP MEMERR
EWRITE:
MOV BX,[PARAM1]
OR BX,BX
JNZ WRT
MOV CX,[ONE4TH]
MOV DI,[ENDTXT]
SUB DI,CX ;Write everything in front of here
JBE RET3
CMP DI,OFFSET DG:START ;See if there's anything to write
JBE RET3
XOR DX,DX
MOV BX,1 ;Look for one more line
CALL SCANLN
JMP SHORT WRTADD
WRT:
INC BX
CALL FINDLIN
WRTADD:
CMP BYTE PTR [DELFLG],0
JNZ WRTADD1
PUSH DI
CALL DELBAK ;Want to delete the .BAK file
;as soon as the first write occurs
POP DI
WRTADD1:
MOV CX,DI
MOV DX,OFFSET DG:START
SUB CX,DX ;Amount to write
JZ RET3
MOV AH,SET_DMA
INT 21H
MOV DX,OFFSET DG:FCB2
MOV AH,FCB_RANDOM_WRITE_BLOCK
INT 21H
OR AL,AL
JNZ WRTERR
MOV SI,DI
MOV DI,OFFSET DG:START
MOV [POINTER],DI
MOV CX,[ENDTXT]
SUB CX,SI
INC CX ;Amount of text remaining
REP MOVSB
DEC DI ;Point to EOF
MOV [ENDTXT],DI
MOV [CURRENT],1
RET
WRTERR:
MOV AH,FCB_CLOSE
INT 21H
MOV DX,OFFSET DG:DSKFUL
xERROR:
MOV AH,STD_CON_STRING_OUTPUT
INT 21H
;-----------------------------------------------------------------------
call rest_dir ;restore to the proper directory
;-----------------------------------------------------------------------
INT 32
RET$5: RET
PAGE:
xor bx,bx ;get last line in the buffer
call findlin
mov [lastlin],dx
mov bx,[param1]
or bx,bx ;was it specified?
jnz frstok ;yes, use it
mov bx,[current]
cmp bx,1 ;if current line =1 start from there
je frstok
inc bx ;start from current+1 line
frstok:
cmp bx,[lastlin] ;check that we are in the buffer
ja ret$5 ;if not just quit
infile:
mov dx,[param2]
or dx,dx ;was param2 specified?
jnz scndok ;yes,....
mov dx,bx ;no, take the end line to be the
add dx,22 ; start line + 23
scndok:
inc dx
cmp dx,[lastlin] ;check that we are in the buffer
jbe infile2
mov dx,[lastlin] ;we are not, take the last line as end
infile2:
cmp dx,bx ;is param1 < param2 ?
jbe ret$5 ;yes, no backwards listing, quit
push dx ;save the end line
push bx ;save start line
mov bx,dx ;set the current line
dec bx
call findlin
mov [pointer],di
mov [current],dx
pop bx ;restore start line
call findlin ;get pointer to start line
mov si,di ;save pointer
pop di ;get end line
sub di,bx ;number of lines
jmp short display
LIST:
MOV BX,[PARAM1]
OR BX,BX
JNZ CHKP2
MOV BX,[CURRENT]
SUB BX,11
JA CHKP2
MOV BX,1
CHKP2:
CALL FINDLIN
JNZ RET7
MOV SI,DI
MOV DI,[PARAM2]
INC DI
SUB DI,BX
JA DISPLAY
MOV DI,23
JMP SHORT DISPLAY
DISPONE:
MOV DI,1
DISPLAY:
; Inputs:
; BX = Line number
; SI = Pointer to text buffer
; DI = No. of lines
; Function:
; Ouputs specified no. of line to terminal, each
; with leading line number.
; Outputs:
; BX = Last line output.
; All registers destroyed.
MOV CX,[ENDTXT]
SUB CX,SI
JZ RET7
MOV BP,[CURRENT]
DISPLN:
PUSH CX
CALL SHOWNUM
POP CX
OUTLN:
LODSB
CMP AL," "
JAE SEND
CMP AL,10
JZ SEND
CMP AL,13
JZ SEND
CMP AL,9
JZ SEND
PUSH AX
MOV AL,"^"
CALL OUT
POP AX
OR AL,40H
SEND:
CALL OUT
CMP AL,10
LOOPNZ OUTLN
JCXZ RET7
INC BX
DEC DI
JNZ DISPLN
DEC BX
RET7: RET
LOADBUF:
MOV DI,2 + OFFSET DG:EDITBUF
MOV CX,255
MOV DX,-1
LOADLP:
LODSB
STOSB
INC DX
CMP AL,13
LOOPNZ LOADLP
MOV [EDITBUF+1],DL
JZ RET7
TRUNCLP:
LODSB
INC DX
CMP AL,13
JNZ TRUNCLP
DEC DI
STOSB
RET
NOTFNDJ:JMP NOTFND
replac_from_curr:
mov byte ptr [srchmod],1 ;search from curr+1 line
jmp short sj6
REPLAC:
mov byte ptr [srchmod],0 ;search from beg of buffer
sj6:
MOV BYTE PTR [SRCHFLG],0
CALL FNDFIRST
JNZ NOTFNDJ
REPLP:
MOV SI,[NUMPOS]
CALL LOADBUF ;Count length of line
SUB DX,[OLDLEN]
MOV CX,[NEWLEN]
ADD DX,CX ;Length of new line
CMP DX,254
JA TOOLONG
MOV BX,[LSTNUM]
PUSH DX
CALL SHOWNUM
POP DX
MOV CX,[LSTFND]
MOV SI,[NUMPOS]
SUB CX,SI ;Get no. of char on line before change
DEC CX
CALL OUTCNT ;Output first part of line
PUSH SI
MOV SI,1+ OFFSET DG:TXT2
MOV CX,[NEWLEN]
CALL OUTCNT ;Output change
POP SI
ADD SI,[OLDLEN] ;Skip over old stuff in line
MOV CX,DX ;DX=no. of char left in line
ADD CX,2 ;Include CR/LF
CALL OUTCNT ;Output last part of line
CALL QUERY ;Check if change OK
JNZ REPNXT
CALL PUTCURS
MOV DI,[LSTFND]
DEC DI
MOV SI,1+ OFFSET DG:TXT2
MOV DX,[OLDLEN]
MOV CX,[NEWLEN]
DEC CX
ADD [LSTFND],CX ;Bump pointer beyond new text
INC CX
DEC DX
SUB [SRCHCNT],DX ;Old text will not be searched
JAE SOMELEFT
MOV [SRCHCNT],0
SOMELEFT:
INC DX
CALL REPLACE
REPNXT:
CALL FNDNEXT
JNZ RET8
JMP REPLP
OUTCNT:
JCXZ RET8
OUTLP:
LODSB
CALL OUT
DEC DX
LOOP OUTLP
RET8: RET
TOOLONG:
MOV DX,OFFSET DG:TOOLNG
JMP SHORT PERR
search_from_curr:
mov byte ptr [srchmod],1 ;search from curr+1 line
jmp short sj7
SEARCH:
mov byte ptr [srchmod],0 ;search from beg of buffer
sj7:
MOV BYTE PTR [SRCHFLG],1
CALL FNDFIRST
JNZ NOTFND
SRCH:
MOV BX,[LSTNUM]
MOV SI,[NUMPOS]
CALL DISPONE
MOV DI,[LSTFND]
MOV CX,[SRCHCNT]
MOV AL,10
REPNE SCASB
JNZ NOTFND
MOV [LSTFND],DI
MOV [NUMPOS],DI
MOV [SRCHCNT],CX
INC [LSTNUM]
CALL QUERY
JZ PUTCURS
CALL FNDNEXT
JZ SRCH
NOTFND:
MOV DX,OFFSET DG:NOSUCH
PERR:
MOV AH,STD_CON_STRING_OUTPUT
INT 21H
RET
PUTCURS:
MOV BX,[LSTNUM]
DEC BX ;Current <= Last matched line
CALL FINDLIN
MOV [CURRENT],DX
MOV [POINTER],DI
RET9: RET
DELETE:
MOV BX,[PARAM1]
OR BX,BX
JNZ DELFIN1
MOV BX,[CURRENT]
CALL CHKRANGE
DELFIN1:
CALL FINDLIN
JNZ RET9
PUSH BX
PUSH DI
MOV BX,[PARAM2]
OR BX,BX
JNZ DELFIN2
MOV BX,DX
DELFIN2:
INC BX
CALL FINDLIN
MOV DX,DI
POP DI
SUB DX,DI
JBE COMERRJ
POP [CURRENT]
MOV [POINTER],DI
XOR CX,CX
JMP SHORT REPLACE
COMERRJ:JMP COMERR
NOCOM:
DEC [COMLINE]
MOV BX,[PARAM1]
OR BX,BX
JNZ HAVLIN
MOV BX,[CURRENT]
INC BX ;Default is current line plus one
CALL CHKRANGE
HAVLIN:
CALL FINDLIN
MOV SI,DI
MOV [CURRENT],DX
MOV [POINTER],SI
jz sj12
ret
sj12:
CMP SI,[ENDTXT]
JZ RET12
CALL LOADBUF
MOV [OLDLEN],DX
MOV SI,[POINTER]
CALL DISPONE
CALL SHOWNUM
MOV AH,STD_CON_STRING_INPUT ;Get input buffer
MOV DX,OFFSET DG:EDITBUF
INT 21H
MOV AL,10
CALL OUT
MOV CL,[EDITBUF+1]
MOV CH,0
JCXZ RET12
MOV DX,[OLDLEN]
MOV SI,2 + OFFSET DG:EDITBUF
;-----------------------------------------------------------------------
call unquote ;scan for quote chars if any
;-----------------------------------------------------------------------
MOV DI,[POINTER]
REPLACE:
; Inputs:
; CX = Length of new text
; DX = Length of original text
; SI = Pointer to new text
; DI = Pointer to old text in buffer
; Function:
; New text replaces old text in buffer and buffer
; size is adjusted. CX or DX may be zero.
; CX, SI, DI all destroyed. No other registers affected.
CMP CX,DX
JZ COPYIN
PUSH SI
PUSH DI
PUSH CX
MOV SI,DI
ADD SI,DX
ADD DI,CX
MOV AX,[ENDTXT]
SUB AX,DX
ADD AX,CX
CMP AX,[LAST]
JAE MEMERR
XCHG AX,[ENDTXT]
MOV CX,AX
SUB CX,SI
CMP SI,DI
JA DOMOV
ADD SI,CX
ADD DI,CX
STD
DOMOV:
INC CX
REP MOVSB
CLD
POP CX
POP DI
POP SI
COPYIN:
REP MOVSB
RET12: RET
MEMERR:
MOV DX,OFFSET DG:MEMFUL
MOV AH,STD_CON_STRING_OUTPUT
INT 21H
JMP COMMAND
MOVERR:
MOV DX,OFFSET DG:BADCOM
ERRORJ:
JMP COMERR
MOVE:
MOV BYTE PTR [MOVFLG],1
JMP SHORT BLKMOVE
COPY:
MOV BYTE PTR [MOVFLG],0
BLKMOVE:
MOV BX,[PARAM3] ;Third parameter must be specified
OR BX,BX
MOV DX,OFFSET DG:DEST
JZ ERRORJ
MOV BX,[PARAM1] ;Get the first parameter
OR BX,BX ;Not specified?
JNZ NXTARG
MOV BX,[CURRENT] ;Defaults to the current line
CALL CHKRANGE
MOV [PARAM1],BX ;Save it since current line may change
NXTARG:
CALL FINDLIN ;Get a pointer to the line
MOV [PTR_1],DI ;Save it
MOV BX,[PARAM2] ;Get the second parameter
OR BX,BX ;Not specified?
JNZ HAVARGS
MOV BX,[CURRENT] ;Defaults to the current line
MOV [PARAM2],BX ;Save it since current line may change
HAVARGS:
;Parameters must not overlap
MOV DX,[PARAM3]
CMP DX,[PARAM1]
JBE NOERROR
CMP DX,[PARAM2]
JBE MOVERR
NOERROR:
INC BX ;Get pointer to line Param2+1
CALL FINDLIN
MOV SI,DI
MOV [PTR_2],SI ;Save it
MOV CX,DI
MOV DI,[PTR_1] ;Restore pointer to line Param1
SUB CX,DI ;Calculate number of bytes to copy
MOV [COPYSIZ],CX ;Save in COPYSIZ
PUSH CX ;And on the stack
MOV AX,[PARAM4] ;Is count specified?
OR AX,AX
JZ MEM_CHECK
MUL [COPYSIZ]
OR DX,DX
JZ COPYSIZ_OK
JMP MEMERR
COPYSIZ_OK:
MOV CX,AX
MOV [COPYSIZ],CX
MEM_CHECK:
MOV AX,[ENDTXT]
MOV DI,[LAST]
SUB DI,AX
CMP DI,CX
JAE HAV_ROOM
JMP MEMERR
HAV_ROOM:
MOV BX,[PARAM3]
PUSH BX
CALL FINDLIN
MOV [PTR_3],DI
MOV CX,[ENDTXT]
SUB CX,DI
INC CX
MOV SI,[ENDTXT]
MOV DI,SI
ADD DI,[COPYSIZ]
MOV [ENDTXT],DI
STD
REP MOVSB
CLD
POP BX
CMP BX,[PARAM1]
JB GET_PTR_2
MOV SI,[PTR_1]
JMP SHORT COPY_TEXT
GET_PTR_2:
MOV SI,[PTR_2]
COPY_TEXT:
MOV BX,[PARAM4]
MOV DI,[PTR_3]
POP CX
MOV [COPYSIZ],CX
COPY_TEXT_1:
REP MOVSB
DEC BX
CMP BX,0
JLE MOV_CHK
MOV [PARAM4],BX
SUB SI,[COPYSIZ]
MOV CX,[COPYSIZ]
JMP SHORT COPY_TEXT_1
MOV_CHK:
CMP BYTE PTR[MOVFLG],0
JZ COPY_DONE
MOV DI,[PTR_1]
MOV SI,[PTR_2]
MOV BX,[PARAM3]
CMP BX,[PARAM1]
JAE DEL_TEXT
ADD DI,[COPYSIZ]
ADD SI,[COPYSIZ]
DEL_TEXT:
MOV CX,[ENDTXT]
SUB CX,SI
REP MOVSB
MOV [ENDTXT],DI
MOV CX,[PARAM2]
SUB CX,[PARAM1]
MOV BX,[PARAM3]
SUB BX,CX
JNC MOVE_DONE
COPY_DONE:
MOV BX,[PARAM3]
MOVE_DONE:
CALL FINDLIN
MOV [POINTER],DI
MOV [CURRENT],BX
RET
MOVEFILE:
MOV CX,[ENDTXT] ;Get End-of-text marker
MOV SI,CX
SUB CX,DI ;Calculate number of bytes to copy
INC CX
MOV DI,DX
STD
REP MOVSB ;Copy CX bytes
XCHG SI,DI
CLD
INC DI
MOV BP,SI
SETPTS:
MOV [POINTER],DI ;Current line is first free loc
MOV [CURRENT],BX ; in the file
MOV [ENDTXT],BP ;End-of-text is last free loc before
RET
NAMERR:
JMP COMERR1
MERGE:
MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 1
MOV DI,OFFSET DG:FCB3
INT 21H
OR AL,AL
MOV DX,OFFSET DG:BADDRV
JNZ NAMERR
MOV [COMLINE],SI
MOV DX,OFFSET DG:FCB3
MOV AH,FCB_OPEN
INT 21H
OR AL,AL
MOV DX,OFFSET DG:FILENM
JNZ NAMERR
MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 23H
MOV DX,OFFSET DG:ABORTMERGE
INT 21H
MOV BX,[PARAM1]
OR BX,BX
JNZ MRG
MOV BX,[CURRENT]
CALL CHKRANGE
MRG:
CALL FINDLIN
MOV BX,DX
MOV DX,[LAST]
CALL MOVEFILE
;Set DMA address for reading in new file
MOV DX,[POINTER]
MOV AH,SET_DMA
INT 21H
XOR AX,AX
MOV WORD PTR DS:[FCB3+fcb_RR],AX
MOV WORD PTR DS:[FCB3+fcb_RR+2],AX
INC AX
MOV WORD PTR DS:[FCB3+fcb_RECSIZ],AX
MOV DX,OFFSET DG:FCB3
MOV CX,[ENDTXT]
SUB CX,[POINTER]
MOV AH,FCB_RANDOM_READ_BLOCK
INT 21H
CMP AL,1
JZ FILEMRG
MOV DX,OFFSET DG:MRGERR
MOV AH,STD_CON_STRING_OUTPUT
INT 21H
MOV CX,[POINTER]
JMP SHORT RESTORE
FILEMRG:
ADD CX,[POINTER]
MOV SI,CX
DEC SI
LODSB
CMP AL,1AH
JNZ RESTORE
DEC CX
RESTORE:
MOV DI,CX
MOV SI,[ENDTXT]
INC SI
MOV CX,[LAST]
SUB CX,SI
REP MOVSB
MOV [ENDTXT],DI
MOV BYTE PTR [DI],1AH
MOV DX,OFFSET DG:FCB3
MOV AH,FCB_CLOSE
INT 21H
MOV DX,OFFSET DG:START
MOV AH,SET_DMA
INT 21H
RET
INSERT:
MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 23H ;Set vector 23H
MOV DX,OFFSET DG:ABORTINS
INT 21H
MOV BX,[PARAM1]
OR BX,BX
JNZ INS
MOV BX,[CURRENT]
CALL CHKRANGE
INS:
CALL FINDLIN
MOV BX,DX
MOV DX,[LAST]
CALL MOVEFILE
INLP:
CALL SETPTS ;Update the pointers into file
CALL SHOWNUM
MOV DX,OFFSET DG:EDITBUF
MOV AH,STD_CON_STRING_INPUT
INT 21H
CALL LF
MOV SI,2 + OFFSET DG:EDITBUF
CMP BYTE PTR [SI],1AH
JZ ENDINS
;-----------------------------------------------------------------------
call unquote ;scan for quote chars if any
;-----------------------------------------------------------------------
MOV CL,[SI-1]
MOV CH,0
MOV DX,DI
INC CX
ADD DX,CX
JC MEMERRJ1
JZ MEMERRJ1
CMP DX,BP
JB MEMOK
MEMERRJ1:
CALL END_INS
JMP MEMERR
MEMOK:
REP MOVSB
MOV AL,10
STOSB
INC BX
JMP SHORT INLP
ABORTMERGE:
MOV DX,OFFSET DG:START
MOV AH,SET_DMA
INT 21H
ABORTINS:
MOV AX,CS ;Restore segment registers
MOV DS,AX
MOV ES,AX
MOV SS,AX
MOV SP,OFFSET DG:STACK
STI
CALL CRLF
CALL ENDINS
JMP COMOVER
ENDINS:
CALL END_INS
RET
END_INS:
MOV BP,[ENDTXT]
MOV DI,[POINTER]
MOV SI,BP
INC SI
MOV CX,[LAST]
SUB CX,BP
REP MOVSB
DEC DI
MOV [ENDTXT],DI
MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 23H
MOV DX,OFFSET DG:ABORTCOM
INT 21H
RET
FILLBUF:
MOV [PARAM1],-1 ;Read in max. no of lines
CALL APPEND
ENDED:
;Write text out to .$$$ file
MOV BYTE PTR [ENDING],1 ;Suppress memory errors
MOV BX,-1 ;Write max. no of lines
CALL WRT
TEST BYTE PTR [HAVEOF],-1
JZ FILLBUF
MOV DX,[ENDTXT]
MOV AH,SET_DMA
INT 21H
MOV CX,1
MOV DX,OFFSET DG:FCB2
MOV AH,FCB_RANDOM_WRITE_BLOCK
INT 21H ;Write end-of-file byte
;Close .$$$ file
MOV AH,FCB_CLOSE
INT 21H
MOV SI,FCB
LEA DI,[SI+fcb_FILSIZ]
MOV DX,SI
MOV CX,9
REP MOVSB
MOV SI,OFFSET DG:BAK
MOVSW
MOVSB
;Rename original file .BAK
MOV AH,FCB_RENAME
INT 21H
MOV SI,FCB
MOV DI,OFFSET DG:FCB2 + fcb_FILSIZ
MOV CX,6
REP MOVSW
;Rename .$$$ file to original name
MOV DX,OFFSET DG:FCB2
INT 21H
call rest_dir ;restore directory if needed
INT 20H
ABORTCOM:
MOV AX,CS
MOV DS,AX
MOV ES,AX
MOV SS,AX
MOV SP,OFFSET DG:STACK
STI
CALL CRLF
JMP COMMAND
DELBAK:
MOV BYTE PTR [DELFLG],1
MOV DI,9+OFFSET DG:FCB2
MOV SI,OFFSET DG:BAK
MOVSW
MOVSB
;Delete old backup file (.BAK)
MOV AH,FCB_DELETE
MOV DX,OFFSET DG:FCB2
INT 21H
MOV DI,9+OFFSET DG:FCB2
MOV AL,"$"
STOSB
STOSB
STOSB
RET
CODE ENDS
END EDLIN