home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload
/
ShartewareOverload.cdr
/
progm
/
dpl.zip
/
_FILEIO.D
< prev
next >
Wrap
Text File
|
1988-07-11
|
24KB
|
1,011 lines
; Doug's Programming Language -- DPL, Version 2.22
; Copyright (c) 1988 Douglas S. Cody, All rights reserved.
;-----------------------=================================----------------------
;-----------------------====< _FILEIO.D STARTS HERE >====----------------------
;-----------------------=================================----------------------
;
SUBPGM _FILEIO
;
; _FILEIO contains all the routines necessary for reading & writing to
; all the different devices in the PC. The following file types
; are supported.
;
; Sequential read/write of ASCII variable length records
; Sequential read/write of ASCII/BINARY fixed length records
; Random read/write of ASCII/BINARY fixed length records
;
; This module contains the following routines:
;
; _FREAD -- READ a device/file
; _FWRITE -- WRITE to a device/file
; _FNOTE -- Return the current file pointer
; _FPOINT -- Set the file pointer
; _FOPEN -- Open a device/file
; _FCLOSE -- Close a device/file
;
;
EXTRN @CR_LF:BYTE
;
BEGIN _FILEIO
EXTRN _STREND:NEAR
RETURN
;
;------------------------===============================-----------------------
;------------------------====< FILE CLOSE ROUTINES >====-----------------------
;------------------------===============================-----------------------
;
; _FCLOSE -- CLOSE AN OPENED FILE
;
; Entry conditions:
; SI points to the file
; Exit conditions:
; STATUS holds the return code
;
PUBLIC _FCLOSE
_FCLOSE PROC NEAR
MOV [STATUS],0
CMP BYTE PTR [SI+@FFOPN],01 ; SHOULD WE CLEAR BUFFERS?
JNZ FCLO_02 ; NO, CONTINUE ON...
CALL @WRT_BUFF_OUT ; YES, FLUSH IT...
;
FCLO_02:
SUB AX,AX ; FLUSH THE FILE STATE
MOV [SI+@FFSTA],AL ; CLEAR THE OLD STATUS
MOV [SI+@FFSPEN],AL ; & THE PENDING STATUS
MOV [SI+@FFPTRL],AX ; CLEAR THE FILE POINTERS
MOV [SI+@FFPTRH],AX
NOT AL
MOV [SI+@FFOPN],AL ; CLEAR THE OPEN STATE
MOV BX,[SI+@FFHAN]
MOV AH,3EH
INT 21H
JNC FCLO_05
MOV [STATUS],AX
;
FCLO_05:
RET
_FCLOSE ENDP
;
;
;-------------------------==============================-----------------------
;-------------------------====< FILE NOTE ROUTINES >====-----------------------
;-------------------------==============================-----------------------
;
; _FNOTE -- NOTE THE CURRENT POSITION OF THE FILE POINTER
;
; Entry conditions:
; SI points to the file
; Exit conditions:
; STATUS holds the return code
;
PUBLIC _FNOTE
_FNOTE PROC NEAR
MOV [STATUS],00
MOV BX,[SI+@FFCLA]
MOV BX,CS:NOTE_TABLE[BX]
JMP BX
;
NOTE_TABLE LABEL WORD
DW NOTE_EXIT
DW NOTE_IT
DW NOTE_IT
DW NOTE_EXIT
;
NOTE_IT:
CMP BYTE PTR [SI+@FFOPN],01 ; WRITE STATE?
JNZ NTE_05 ; NO, NO NEED TO WORRY
CALL @WRT_BUFF_OUT ; YES, DUMP THE BUFFER FIRST
;
NTE_05:
MOV BX,[SI+@FFPTRL]
MOV [DI+0],BX
MOV BX,[SI+@FFPTRH]
MOV [DI+2],BX
;
NOTE_EXIT:
RET
_FNOTE ENDP
;
;
;------------------------==============================------------------------
;------------------------====< FILE OPEN ROUTINES >====------------------------
;------------------------==============================------------------------
;
; _FOPEN -- OPEN A DOS FILE
;
; Entry conditions:
; SI points to the file
; Exit conditions:
; STATUS holds the return code
;
PUBLIC _FOPEN
_FOPEN PROC NEAR
MOV [STATUS],0
CMP BYTE PTR [SI+@FFOPN],0FFH ; ALREADY OPENED?
JNE OPENED ; YES, EXIT IN ERROR
;
; PERFORM HOUSEKEEPING ON THE CONTROL BLOCK
;
MOV BX,[SI+@FFCLA]
MOV BX,CS:OPEN_TABLE[BX]
JMP BX
;
OPEN_TABLE LABEL WORD
DW OPEN_CHAR_DEV
DW OPEN_SEQ_FILE
DW OPEN_SEQ_FILE
DW OPEN_RND_FILE
;
OPENED:
MOV [STATUS],5
RET
;
;----------------------------------------
;
OPEN_CHAR_DEV:
PUSH AX ; SAVE THE OPEN CODE
MOV AH,3DH
LEA DX,@FFNAM[SI] ; DX POINTS TO THE FILE NAME
SUB CX,CX
INT 21H ; OPEN AN EXISTING FILE
JNC OPCHR_10 ; CONTINUE ON IF GOOD...
MOV [STATUS],AX
POP AX ; FLUSH...
RET
;
OPCHR_10:
MOV [SI+@FFHAN],AX ; SAVE THE HANDLE
POP AX
MOV [SI+@FFOPN],AL ; SAVE THE OPEN STATE
RET
;
;----------------------------------------
;
OPEN_SEQ_FILE:
MOV BX,[SI+@FFBUF] ; CALCUATE THE NEW BUFFER POINTER
MOV WORD PTR [BX+@RCUR],00 ; CLEAR THE REMAINING COUNT
ADD BX,@RDAT
MOV [SI+@FFBPTR],BX
;
CMP AL,02 ; ATTEMPTING IO ON A SEQUENTIAL FILE?
JNZ OPSQ_05 ; NO, CONTINUE ON...
MOV [STATUS],01 ; YES, BOMB OUT
RET
;
OPSQ_05:
PUSH AX ; SAVE THE OPEN CODE
MOV AH,3DH
LEA DX,@FFNAM[SI] ; DX POINTS TO THE FILE NAME
SUB CX,CX
CMP AL,01 ; OUTPUT?
JZ OPSQ_10 ; YES, CONTINUE ON...
INT 21H ; OPEN AN EXISTING FILE
JNC OPSQ_15 ; CONTINUE ON IF GOOD...
;
OPSQ_07:
MOV [STATUS],AX
POP AX ; FLUSH...
RET
;
OPSQ_10:
MOV AH,3CH ; 'CREATE' a file
INT 21H
JC OPSQ_07 ; EXIT IN ERROR
;
OPSQ_15:
MOV [SI+@FFHAN],AX ; SAVE THE HANDLE
POP AX
MOV [SI+@FFOPN],AL ; SAVE THE OPEN STATE
RET
;
;---------------------------------------
;
OPEN_RND_FILE:
PUSH AX ; SAVE THE MODE
MOV AH,3DH
LEA DX,@FFNAM[SI] ; DX POINTS TO THE FILE NAME
INT 21H ; OPEN THE FILE
JC OPRN_05 ; EXIT IF IN ERROR
;
OPRN_00:
MOV [SI+@FFHAN],AX ; SAVE THE HANDLE
POP BX ; GET THE OPEN STATE
MOV [SI+@FFOPN],BL
RET
;
OPRN_05:
POP BX ; GET THE OPEN MODE
PUSH BX ; & SAVE AGAIN
CMP AX,02 ; FILE-NOT-FOUND ERROR?
JNZ OPRN_10 ; NO, EXIT DO TO OTHER ERROR
CMP BL,0 ; READ ATTEMPT?
JZ OPRN_10 ; YES, EXIT BAD
MOV AH,3CH ; TRY TO CREATE A FILE
SUB CX,CX ; MAKE IT A USEFUL FILE
LEA DX,@FFNAM[SI] ; DX POINTS TO THE FILE NAME
INT 21H
JNC OPRN_00 ; EXIT IF GOOD
;
OPRN_10:
MOV [STATUS],AX ; SAVE THE BAD RETURN CODE
POP BX ; FLUSH...
RET
_FOPEN ENDP
;
;------------------------===============================-----------------------
;------------------------====< FILE POINT ROUTINES >====-----------------------
;------------------------===============================-----------------------
;
; _FPOINT -- MOVE A FILE POINTER
;
; Entry conditions:
; SI points to the file
; Exit conditions:
; STATUS holds the return code
;
PUBLIC _FPOINT
_FPOINT PROC NEAR
MOV [STATUS],0
MOV BX,[SI+@FFCLA]
MOV BX,CS:POINT_TABLE[BX]
JMP BX
;
POINT_TABLE LABEL WORD
DW POINT_EXIT
DW POINT_SEQ
DW POINT_SEQ
DW POINT_EXIT
;
POINT_SEQ:
CMP BYTE PTR [SI+@FFOPN],01 ; WRITE STATE?
JNZ PNT_05 ; NO, NO NEED TO WORRY
CALL @WRT_BUFF_OUT ; YES, DUMP THE BUFFER FIRST
;
PNT_05:
MOV BX,[SI+@FFBUF] ; FLUSH THE BUFFER
MOV WORD PTR [BX+@RCUR],00
ADD BX,@RDAT
MOV [SI+@FFBPTR],BX
SUB BL,BL ; CLEAR THE EOF FLAGS
MOV [SI+@FFSTA],BL
MOV [SI+@FFSPEN],BL
MOV DX,[DI+0] ; GET THE LSW
MOV CX,[DI+2] ; GET THE MSW
CALL @DO_POINT ; MOVE THE POINTERS
;
POINT_EXIT:
RET
_FPOINT ENDP
;
;--------------------------==============================----------------------
;--------------------------====< FILE READ ROUTINES >====----------------------
;--------------------------==============================----------------------
;
; _FREAD -- READ DATA FROM A FILE
;
; Entry conditions:
; SI holds the file handle
; DI holds the target string/record
; CX holds the length, if the file is an ascii file
;
; Exit conditions:
; STATUS holds the result of the read
;
PUBLIC _FREAD
_FREAD PROC NEAR
MOV AL,[SI+@FFSPEN] ; ANY PENDING STATUS?
OR AL,AL ; (CHECKING...)
JZ _FRD_05 ; NO, CONTINUE ON...
MOV [SI+@FFSTA],AL ; YES, SO SET THE BAD STATUS
;
_FRD_00:
SUB AH,AH
MOV [STATUS],AX
MOV [SI+@FFSPEN],AH ; CLEAR THE PENDING STATUS
RET
;
_FRD_05:
MOV AL,[SI+@FFSTA] ; ANY BAD STATUS?
OR AL,AL
JNZ _FRD_00 ; YES, EXIT NOW...
CMP BYTE PTR [SI+@FFOPN],01 ; OPENED FOR WRITING?
JZ BAD_READ ; YES, EXIT BAD
MOV [STATUS],0
MOV BX,[SI+@FFCLA] ; GET THE FILE CLASS TYPE
MOV BX,CS:READ_TBL[BX] ; & USE AS AN INDEX
JMP BX
;
READ_TBL LABEL WORD
DW READ_CHAR_DEV
DW READ_TXT_SEQ
DW READ_BIN_SEQ
DW READ_BIN_RND
;
BAD_READ:
MOV [STATUS],05
RET
;
;----------------------------------------
; READ FROM A CHARACTER DEVICE (CON,AUX,COM1,COM2,ETC.)
;
READ_CHAR_DEV:
PUSH ES
PUSH DS
POP ES ; ES = DATA SEGMENT
;
JCXZ RD_CON_10 ; EXIT IF NULL
MOV DX,DI ; DX = TARGET STRING
MOV BX,[SI+@FFHAN] ; GET THE HANDLE
MOV AH,3FH
INT 21H ; READ...
JNC RD_CON_05 ; CONTINUE IF NOT IN ERROR
;
MOV [STATUS],AX
POP ES
RET
;
RD_CON_05:
MOV CX,AX
JCXZ RD_CON_09 ; GO SET THE TERMINATOR
MOV AL,0DH
CLD
REPNE SCASB ; FIND A C/R
JNE RD_CON_09 ; NOT FOUND, SAVE ENTIRE STRING
DEC DI ; FLUSH THE C/R
;
RD_CON_09:
SUB AL,AL
STOSB ; SET THE TERMINATOR
;
RD_CON_10:
POP ES
RET
;
; READ FROM AN ASCII FILE
;
READ_TXT_SEQ:
PUSH ES ; + 14 UNK
PUSH DS
POP ES
PUSH BP ; + 12 UNDEFINED
PUSH DI ; + 10 TARGET STRING
PUSH CX ; + 8 TARGET STRING LENGTH
PUSH SI ; + 6 FILE ADDRESS
MOV DI,[SI+@FFBUF] ; GET THE BUFFER ADDRESS
MOV AX,[SI+@FFBPTR] ; GET THE BUFFER POINTER
PUSH AX ; + 4 BUFFER POINTER
MOV DX,[DI+@RLEN] ; GET THE RECORD LENGTH
MOV CX,[DI+@RCUR] ; GET THE RECORD REMAINING COUNT
PUSH CX ; + 2 REMAINING BUFFER COUNT
SUB DX,CX ; DX = AVAILABLE SPACE IN BUFFER
PUSH DI ; + 0 BUFFER ADDRESS
;
MOV BP,SP ; FRAME THE STACK
;
; MAKE SURE THERE IS DATA IN THE BUFFER
;
MOV AX,[BP+2] ; GET THE # OF BYTES AVAILABLE
CMP AX,[BP+8] ; HAVE ENOUGH IN THE BUFFER FOR THE WHOLE READ?
JG RD_TXT_15 ; YES, SKIP TO THE READ EXTRACTION
;
ADD DI,@RDAT ; DI POINTS TO THE START OF THE BUFFER DATA
MOV SI,[BP+4] ; GET THE OLD POINTER
MOV [BP+4],DI ; SAVE THE NEW POINTER
JCXZ RD_TXT_AA ; EXIT IF FULL
CLD
REP MOVSB ; MOVE THE DATA TO THE FRONT OF THE BUFFER
;
RD_TXT_AA:
;
; READ THE FILE FOR MORE DATA
;
MOV CX,DX ; ALL FULL?
JCXZ RD_TXT_09 ; YES, CONTINUE ON...
;
MOV DX,DI ; GET THE TARGET POINTER
MOV SI,[BP+6] ; GET THE FILE ADDR
MOV BX,[SI+@FFHAN] ; BX = HANDLE
MOV AH,3FH ; FUNCTION...
INT 21H
JNC RD_TXT_10 ; GOOD READ
;
RD_TXT_05:
MOV [STATUS],AX
MOV SI,[BP+6] ; GET THE FILE ADDR
MOV [SI+@FFSTA],AL
;
RD_TXT_07:
ADD SP,12 ; DE-FRAME...
POP BP
POP ES
RET
;
RD_TXT_09:
MOV AX,CX ; CLEARS AX
;
RD_TXT_10:
ADD AX,[BP+2] ; CALC THE FULL DATA SIZE
JNZ RD_TXT_15 ; SOME DATA IS PRESENT...
INC AX ; AX = 1
JMP SHORT RD_TXT_05 ; EXIT BAD...
;
; THERE IS AT LEAST ONE BYTE AVAILABLE TO BE MOVED
;
RD_TXT_15:
MOV DX,AX ; DX = SOURCE LENGTH
MOV SI,[BP+4] ; GET BUFFER POINTER
MOV DI,[BP+10] ; GET TARGET STRING
MOV CX,[BP+8] ; GET THE TARGET LENGTH
MOV BX,0A0DH
MOV AH,01AH ; AH = ^Z
;
CMP [SI],BH ; LEADING L/F?
JNZ RD_TXT_20 ; NO, CONTINUE ON...
DEC DX ; YES, IS THE LAST CHAR A L/F?
OR DX,DX ; (CHECKING...)
JZ RD_TXT_30 ; YES, GO LOSE IT...
INC SI ; NO, MOVE PAST IT ANYWAY
CMP [SI],AH ; ^Z?
JNZ RD_TXT_20 ; NO, GO MOVE SOME TEXT
DEC SI ; YES, MAKE A FALSE EOF
JMP SHORT RD_TXT_30
;
RD_TXT_20:
DEC DX
JS RD_TXT_30 ; OUT OF DATA, EXIT NOW
LODSB ; FETCH THE CHARACTER
CMP AL,AH ; ^Z
JZ RD_TXT_30
CMP AL,BL ; C/R
JZ RD_TXT_25
CMP AL,BH ; L/F
JZ RD_TXT_25
STOSB
;
RD_TXT_21:
LOOP RD_TXT_20
;
RD_TXT_25:
SUB AL,AL
STOSB ; SET THE TERMINATOR
MOV AX,SI ; SAVE THE END POINTER
;
RD_TXT_26:
MOV SI,[BP+0] ; GET THE BUFFER
MOV [SI+@RCUR],DX ; SAVE THE NEW REMAINDER
MOV SI,[BP+6] ; GET THE FILE OFFSET
MOV [SI+@FFBPTR],AX ; SET THE NEW BUFFER POINTER
MOV BX,[BP+4] ; GET THE ORIGINAL POINTER
SUB AX,BX ; AX HOLDS THE # OF BYTES EXTRACTED
ADD [SI+@FFPTRL],AX ; ADD TO THE FILE POINTER
ADC WORD PTR [SI+@FFPTRH],0
JMP RD_TXT_07 ; & EXIT HOME
;
RD_TXT_30:
SUB AL,AL
STOSB ; SET THE TERMINATOR
MOV AX,[BP+4] ; GET THE BUFFER POINTER
CMP AX,SI ; ANY DATA READ?
MOV AX,[BP+6] ; (GET THE FILE ADDR FIRST...)
XCHG AX,SI ; AX = BUF PTR, SI = FILE PTR
JZ RD_TXT_35 ; NO, CONTINUE ON...
MOV BYTE PTR [SI+@FFSPEN],01; EOF PENDING ON NEXT READ
JMP SHORT RD_TXT_26
;
RD_TXT_35:
MOV BYTE PTR [SI+@FFSTA],01; EOF PENDING RIGHT NOW
MOV [STATUS],01
JMP SHORT RD_TXT_26
;
;---------------------------------------
; READ_BIN_SEQ -- READ A BINARY SEQUENTIAL FILE USING
; FIXED RECORD LENGTH ACCESS
;
READ_BIN_SEQ:
PUSH ES ; + 14 UNK
PUSH DS
POP ES
PUSH BP ; + 12 UNDEFINED
PUSH DI ; + 10 TARGET RECORD ADDRESS
MOV CX,[DI+@RLEN] ; GET THE TARGET RECORD LENGTH & SAVE
PUSH CX ; + 8 TARGET STRING LENGTH
PUSH SI ; + 6 FILE ADDRESS
MOV DI,[SI+@FFBUF] ; GET THE BUFFER ADDRESS
MOV AX,[SI+@FFBPTR] ; GET THE BUFFER POINTER
PUSH AX ; + 4 BUFFER POINTER
MOV DX,[DI+@RLEN] ; GET THE RECORD LENGTH
MOV CX,[DI+@RCUR] ; GET THE RECORD REMAINING COUNT
PUSH CX ; + 2 REMAINING BUFFER COUNT
SUB DX,CX ; DX = AVAILABLE SPACE IN BUFFER
PUSH DI ; + 0 BUFFER ADDRESS
;
MOV BP,SP ; FRAME THE STACK
;
; MAKE SURE THERE IS DATA IN THE BUFFER
;
MOV AX,[BP+2] ; GET THE # OF BYTES AVAILABLE
CMP AX,[BP+8] ; HAVE ENOUGH IN THE BUFFER FOR THE WHOLE READ?
JG RD_BSEQ_15 ; YES, SKIP TO THE READ EXTRACTION
;
ADD DI,@RDAT ; DI POINTS TO THE START OF THE BUFFER DATA
MOV SI,[BP+4] ; GET THE OLD POINTER
MOV [BP+4],DI ; SAVE THE NEW POINTER
JCXZ RD_BSEQ_00 ; EXIT IF FULL
CLD
REP MOVSB ; MOVE THE DATA TO THE FRONT OF THE BUFFER
;
RD_BSEQ_00:
;
; READ THE FILE FOR MORE DATA
;
MOV CX,DX ; ALL FULL?
JCXZ RD_BSEQ_09 ; YES, CONTINUE ON...
;
MOV DX,DI ; GET THE TARGET POINTER
MOV SI,[BP+6] ; GET THE FILE ADDR
MOV BX,[SI+@FFHAN] ; BX = HANDLE
MOV AH,3FH ; FUNCTION...
INT 21H
JNC RD_BSEQ_10 ; GOOD READ
;
RD_BSEQ_05:
MOV [STATUS],AX
MOV SI,[BP+6] ; GET THE FILE ADDR
MOV [SI+@FFSTA],AL
;
RD_BSEQ_07:
ADD SP,12 ; DE-FRAME...
POP BP
POP ES
RET
;
RD_BSEQ_09:
MOV AX,CX ; CLEARS AX
;
RD_BSEQ_10:
ADD AX,[BP+2] ; CALC THE FULL DATA SIZE
JNZ RD_BSEQ_15 ; SOME DATA IS PRESENT...
INC AX ; AX = 1
JMP SHORT RD_BSEQ_05 ; EXIT BAD...
;
; THERE IS AT LEAST ONE BYTE AVAILABLE TO BE MOVED
;
RD_BSEQ_15:
MOV DX,AX ; DX = SOURCE LENGTH
MOV CX,[BP+8] ; GET THE TARGET LENGTH
CMP CX,DX ; IS TARGET GT THE REST OF THE FILE?
JLE RD_BSEQ_20 ; NO, MOVE THE DATA
MOV CX,DX ; YES, SO MOVE IT & SET AN EOF
MOV SI,[BP+6] ; GET THE FILE
MOV BYTE PTR [SI+@FFSTA],01 ; SET THE EOF
MOV [STATUS],01 ; SET IMMEDIATE STATUS TOO
;
RD_BSEQ_20:
SUB DX,CX ; DX HOLDS THE AMOUNT TO BE EXTRACTED
MOV SI,[BP+4] ; GET BUFFER POINTER
MOV DI,[BP+10] ; GET TARGET RECORD
MOV [DI+@RCUR],CX ; SAVE THE AMOUNT MOVED
ADD DI,@RDAT ; MOVE TO THE START OF THE DATA PORTION
REP MOVSB ; MOVE THE ENTIRE RECORD
;
MOV AX,SI ; SAVE THE END POINTER
MOV SI,[BP+0] ; GET THE BUFFER
MOV [SI+@RCUR],DX ; SAVE THE NEW REMAINDER
MOV SI,[BP+6] ; GET THE FILE OFFSET
MOV [SI+@FFBPTR],AX ; SET THE NEW BUFFER POINTER
MOV BX,[BP+4] ; GET THE ORIGINAL POINTER
SUB AX,BX ; AX HOLDS THE # OF BYTES EXTRACTED
ADD [SI+@FFPTRL],AX ; ADD TO THE FILE POINTER
ADC WORD PTR [SI+@FFPTRH],0
JMP RD_BSEQ_07 ; & EXIT HOME
;
;---------------------------------------
; READ_BIN_RND -- READ A BINARY RANDOM FILE USING
; FIXED RECORD LENGTH ACCESS
;
READ_BIN_RND:
CALL @RND_POINT ; SET THE RANDOM FILE POINTER
JC RDBR_05 ; EXIT IF BAD
CALL @READ_IT ; PERFORM THE DOS I/O
MOV BYTE PTR [SI+@FFSTA],00 ; KILL ANY PERMENANT EOF
;
RDBR_05:
RETURN
_FREAD ENDP
;
;-------------------------===============================----------------------
;-------------------------====< FILE WRITE ROUTINES >====----------------------
;-------------------------===============================----------------------
;
; _FWRT -- WRITE DATA TO AN OPENED FILE
;
; Entry conditions:
; SI points to the data/record
; DI points to the file
; CX holds the count, if the write is to an ascii file
; Exit conditions:
; STATUS holds the return code
;
PUBLIC _FWRT
_FWRT PROC NEAR
MOV [STATUS],00
CMP BYTE PTR [DI+@FFOPN],00 ; OPENED FOR READING ONLY?
JZ BAD_WRITE ; YES, SKIP OUT
MOV BX,[DI+@FFCLA] ; USE THE CLASS FOR AN INDEX
MOV BX,CS:WRT_TABLE[BX]
JMP BX
;
WRT_TABLE LABEL WORD
DW _WRT_UNBUF_SEQ
DW _WRT_ASC_SEQ
DW _WRT_BIN_SEQ
DW _WRT_BIN_RND
;
BAD_WRITE:
MOV [STATUS],5 ; DENIED ACCESS
RET
;
;
;---------------------------------------
; _WRT_ASC_SEQ -- WRITE ASCII TEXT TO THE DEVICE
;
; Entry conditions:
; AX holds the CR/LF flag
; SI points to the text
; DI points to the file
;
; Exit conditions:
; STATUS holds the return code
;
_WRT_ASC_SEQ:
PUSH AX ; SAVE THE CR/LF FOR LATER
OR SI,SI ; ANY TEXT?
JZ WRTAS_05 ; NO, CONTINUE ON...
MOV DX,SI ; DX POINTS TO THE TEXT
CALL _STREND ; CX HOLDS THE LENGTH
CALL @WRT_TO_BUFF ; WRITE IT TO THE FILE
JNC WRTAS_05
POP AX ; FLUSH THE STACK
;
WRTAS_EXIT:
RET
;
WRTAS_05:
POP AX
OR AL,AL ; DO A CR/LF?
JZ WRTAS_EXIT ; NO, CONTINUE ON...
MOV CX,2
MOV DX,OFFSET @CR_LF
CALL @WRT_TO_BUFF ; YES, DO IT NOW...
JMP SHORT WRTAS_EXIT
;
;
;---------------------------------------
; _WRT_UNBUF_SEQ -- WRITE ASCII TEXT TO UNBUFFERED OUTPUT
;
; Entry conditions:
; AX holds the CR/LF flag
; SI points to the text
; DI points to the file
;
; Exit conditions:
; STATUS holds the return code
;
_WRT_UNBUF_SEQ:
PUSH AX ; SAVE THE CR/LF FOR LATER
OR SI,SI ; ANY TEXT?
JZ WRTUN_05 ; NO, CONTINUE ON...
MOV DX,SI ; DX POINTS TO THE TEXT
CALL _STREND ; CX HOLDS THE LENGTH
CALL @WRT_IT ; WRITE IT TO THE FILE
JNC WRTUN_05
POP AX ; FLUSH THE STACK
;
WRTUN_EXIT:
RET
;
WRTUN_05:
POP AX
OR AL,AL ; DO A CR/LF?
JZ WRTUN_EXIT ; NO, CONTINUE ON...
MOV CX,2
MOV DX,OFFSET @CR_LF
CALL @WRT_IT ; YES, DO IT NOW...
JMP SHORT WRTUN_EXIT
;
;
;---------------------------------------
; _WRT_BIN_RND -- WRITE BINARY RECORD TO THE DEVICE
;
; Entry conditions:
; AX holds the CR/LF flag
; SI points to the record
; DI points to the file
;
; Exit conditions:
; STATUS holds the return code
;
_WRT_BIN_RND:
XCHG SI,DI ; SETUP FOR THE NEXT CALL
CALL @RND_POINT
JC WRBIRN_05
XCHG SI,DI
LEA DX,@RDAT[SI] ; DX POINTS TO THE TEXT
MOV CX,[SI+@RLEN] ; CX HOLDS THE WHOLE LENGTH
CALL @WRT_IT ; WRITE IT TO THE FILE
;
WRBIRN_05:
RET
;
;
;---------------------------------------
; _WRT_BIN_SEQ -- WRITE BINARY RECORD TO THE DEVICE
;
; Entry conditions:
; AX holds the CR/LF flag
; SI points to the record
; DI points to the file
;
; Exit conditions:
; STATUS holds the return code
;
_WRT_BIN_SEQ:
LEA DX,@RDAT[SI] ; DX POINTS TO THE TEXT
MOV CX,[SI+@RLEN] ; CX HOLDS THE CURRENT LENGTH
CALL @WRT_TO_BUFF ; WRITE IT TO THE FILE
RET
_FWRT ENDP
;
;
;=====================
; ROUTINE SECTION
; LEVEL 1
;=====================
;
;
;---------------------------------------
; @READ_IT -- READ THE BINARY FILE AT THE CURRENT POSITION.
; RECORD THE NEW FILE POSITION
;
; Entry conditions:
; SI points to the file
; DI points to the record
; Exit conditions:
; CARRY set = error
;
@READ_IT PROC NEAR
MOV BX,[SI+@FFHAN] ; BX = FILE HANDLE
MOV CX,[DI+@RLEN] ; CX = BLOCK LENGTH
LEA DX,@RDAT[DI] ; DX POINTS TO THE TARGET DATA AREA
MOV AX,3F00H
INT 21H
JC @RDIT_05 ; EXIT IF IN ERROR
MOV [DI+@RCUR],AX ; SAVE THE NEW RECORD LENGTH
CMP AX,[DI+@RLEN] ; DID WE GET THE WHOLE RECORD?
JZ @RDIT_10 ; YES, EXIT GOOD
MOV AX,01 ; NO, SO SET AN EOF
;
@RDIT_05:
MOV [STATUS],AX
MOV [SI+@FFSTA],AL ; SAVE IN THE FILE TOO...
;
@RDIT_10:
RET
@READ_IT ENDP
;
;
;----------------------------------------
; @RND_POINT -- SET THE NEW FILE POINTER BASED
; UPON THE KEY * FILE RECORD LENGTH
;
; Entry conditions:
; SI points to the opened file
; DI points to the record
; Exit conditions:
; CARRY set = error
; CX,DX,AX modified
;
@RND_POINT PROC NEAR
MOV AX,[DI+@RLEN] ; GET THE LENGTH FROM THE RECORD
MOV BX,[SI+@FFKYW] ; GET THE KEY OFFSET
MOV BX,[BX]
MUL BX ; DX:AX HOLDS THE FILE POINTER
MOV CX,DX
MOV DX,AX ; CX:DX MUST FOR DOS
CALL @DO_POINT
RET
@RND_POINT ENDP
;
;
;----------------------------------------
; @WRT_BUFF_OUT -- WRITE THE BUFFER TO THE DISK FILE
;
; Entry conditions:
; SI points to the opened file
; Exit conditions:
; CARRY set = error
; CX,DX,AX,BX modified
;
@WRT_BUFF_OUT PROC NEAR
MOV CX,[SI+@FFBPTR] ; GET THE CURRENT BUFFER POINTER
MOV DX,[SI+@FFBUF] ; & RESET IT
OR DX,DX ; ANY BUFFER USED?
JZ WRTBFO_05 ; NO, EXIT HOME
ADD DX,@RDAT ; YES, CALC THE DATA ADDRESS
SUB CX,DX ; CX HOLDS THE LENGTH
JCXZ WRTBFO_05 ; CONTINUE ON IF NULL
XCHG SI,DI
CALL @WRT_IT
XCHG SI,DI
;
WRTBFO_05:
RET
@WRT_BUFF_OUT ENDP
;
;
;----------------------------------------
; @WRT_IT -- WRITE DATA TO THE DEVICE/FILE
;
; Entry conditions:
; DI points to the opened file
; DX points to the data
; CX holds the length
; Exit conditions:
; CARRY set = error
; CX,DX,AX,BX modified
;
@WRT_IT PROC NEAR
CALL @WRT_DATA
JC WRTIT_BAD
ADD [DI+@FFPTRL],AX ; CALC THE NEW POINTER
ADC WORD PTR [DI+@FFPTRH],0
CLC
;
WRTIT_BAD:
RET
@WRT_IT ENDP
;
;
;----------------------------------------
; @WRT_TO_BUFF -- WRITE DATA TO THE BUFFER THEN TO DEVICE/FILE
;
; Entry conditions:
; DI points to the opened file
; DX points to the data
; CX holds the length
; Exit conditions:
; CARRY set = error
; CX,DX,AX,BX modified
;
@WRT_TO_BUFF PROC NEAR
MOV AX,[DI+@FFBPTR] ; GET THE CURRENT BUFFER POINTER
MOV BX,[DI+@FFBUF] ; AND THE START OF THE BUFFER
SUB AX,BX ; AX = LENGTH USED + 4
SUB AX,@RDAT
MOV BX,[BX] ; GET THE FULL BUFFER LENGTH
SUB BX,AX ; BX HOLDS THE USEABLE SPACE...
CMP BX,CX ; ANY ROOM LEFT?
JGE @WRTBF_05 ; YES, GO FILL IT...
;
PUSH CX ; SAVE THE COUNT
PUSH DX ; SAVE THE DATA PTR
MOV CX,AX ; CX = LENGTH TO WRITE
MOV DX,[DI+@FFBUF] ;
ADD DX,@RDAT ; DX = BUFFER
CALL @WRT_DATA ; GO WRITE THE BUFFER TO DISK
POP DX ; GET THE ORIGINAL DATA POINTER
POP CX ; AND LENGTH
JC WRTBF_BAD ; EXIT IF BAD
ADD [DI+@FFPTRL],AX ; CALC THE NEW POINTER
ADC WORD PTR [DI+@FFPTRH],0
;
@WRTBF_05:
PUSH SI ; SAVE WHATEVER...
PUSH DI ; SAVE THE FILE
MOV DI,[DI+@FFBPTR] ; GET THE BUFFER POINTER
MOV SI,DX ; SI POINTS TO THE SOURCE
PUSH ES
PUSH DS
POP ES
CLD
REP MOVSB ; MOVE ALL THE BYTES INTO THE BUFFER
POP ES
POP SI ; GET THE FILE
MOV [SI+@FFBPTR],DI ; SAVE THE NEW POINTER
MOV DI,SI
POP SI
CLC
RET
;
WRTBF_BAD:
RET
RET
@WRT_TO_BUFF ENDP
;
;
;=====================
; ROUTINE SECTION
; LEVEL 2
;=====================
;
;
;---------------------------------------
; @DO_POINT -- POINT TO THE NEW FILE LOCATION
;
; Entry conditions:
; SI points to the file
; CX:DX holds the new pointer
; Exit conditions:
; CARRY set = error
;
@DO_POINT PROC NEAR
MOV AX,4200H
MOV BX,[SI+@FFHAN]
INT 21H
JNC @DOPT_05
MOV [STATUS],AX
RET
;
@DOPT_05:
MOV [SI+@FFPTRL],AX ; SET THE CURRENT POSITION
MOV [SI+@FFPTRH],DX
RET
@DO_POINT ENDP
;
;
;----------------------------------------
; @WRT_DATA -- WRITE DATA TO THE DEVICE/FILE
;
; Entry conditions:
; DI points to the opened file
; DX points to the data
; CX holds the length
; Exit conditions:
; CARRY set = error
; CX,DX,AX,BX modified
; IF GOOD, AX HOLDS THE BYTES WRITTEN
;
@WRT_DATA PROC NEAR
CLC
JCXZ WRTDT_EXIT ; EXIT IF NO DATA
MOV BX,[DI+@FFBUF] ; RESET THE BUFFER POINTER
OR BX,BX ; ANY BUFFER USED?
JZ WRTDT_02 ; NO, CONTINUE ON...
ADD BX,@RDAT
MOV [DI+@FFBPTR],BX
;
WRTDT_02:
MOV BX,[DI+@FFHAN] ; GET THE HANDLE
MOV AH,40H
INT 21H
JNC WRTDT_05 ; CONTINUE IF NOT IN ERROR
MOV [STATUS],AX
RET
;
WRTDT_05:
CMP AX,CX ; ALL WRITTEN?
JZ WRTDT_EXIT ; YES, CONTINUE GOOD
MOV BYTE PTR [DI+@FFSTA],01 ; NO, SET AN EOF STATUS
MOV [STATUS],01
STC
;
WRTDT_EXIT:
RET
@WRT_DATA ENDP
;
ENDPGM _FILEIO
;