home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Shareware - Software Farm 2
/
wosw_2.zip
/
wosw_2
/
PASCAL
/
TEXTF.ZIP
/
TEXTF.ASM
next >
Wrap
Assembly Source File
|
1989-08-27
|
14KB
|
446 lines
; textf.ASM
; TASM routines for use with Unit RLINE.PAS.
; Compile with: "TASM RLINE" to create RLINE.OBJ
; Modifed to use object by Arthur Zatarain 09/25/89
CODE SEGMENT BYTE PUBLIC
ASSUME CS:CODE
PUBLIC rfrec@FRead
public rfrec@FReadLn
public rfrec@FOpen
public rfrec@FClose
public rfrec@FSeek
; set up a STRUCture compatible with the Pascal RFrec Record.
RFrec STRUC
Handle dw ? ; File handle
BufStart dw ? ; Offset Disk buffer
BufES dw ? ; Segment Disk buffer
BufDI dw ? ; Current buffer position = si
BSize dw ? ; Buffer size
BufCX dw ? ; Bytes left to search
NBufs dw ? ; Number of buffers read.
TotRead dw ? ; Total bytes last read into buffer.
RFrec ENDS
; Equates for later reference in FRead and FReadLn.
; These offsets reflect the position after the push BP that always appears
; at the start of a procedure, not to the actual position on the stack at
; the time of the call.
RFWordSize EQU 8 ; size of RFrec in words.
RF EQU dword ptr [bp+6] ; address of RFrec
RString EQU dword ptr [bp+10] ; address of Return String
RCh EQU dword ptr [bp+10] ; address of Return Char
;************* The following PROCs are NOT PUBLIC and are NEAR *************
;----------------------------------------------------------------------
; BufMove -
; Appends CX number of bytes from ES:DI to RString.
; Will not move more than 255 bytes to RString. If there are more to move,
; the rest are thrown away.
; Leading ^J's are stripped.
;
; Inputs: ES:DI = address of bytes to move from.
; CX = # Bytes to move. If CX = 0, length byte is set.
; DX = current length of RString
; RString is at [BP+6]
;
; AX Destroyed BX Unaffected CX Destroyed DX updated
; DS Restored SI Destroyed ES Restored DI Destroyed
;
BufMove PROC NEAR
push ds ; save RF segment
push es ; DS = Source segment.
pop ds
mov si, di ; SI = Source offset.
jcxz LengthOK ; Any bytes to move?
cmp byte ptr [si], 10 ; A ^J?
jne NoCtrlJ ; Not ^J, go on.
dec cx ; Is ^J.
inc si
NoCtrlJ: mov ax, 255 ; ax = max length RString can be.
cmp dx, ax ; RString already at max length?
je Bdone ; Yes. Get out.
sub ax, dx ; AX = 255. DX = length(Rstring)
cmp cx, ax ; are there more than max to move?
jbe LengthOK ; If not, go on.
mov cx, ax ; yes. set cx to ax.
LengthOK: les di, RString ; es:di points to RString[0]
mov al, dl ; AL = Length(RString)
add al, cl ; Add bytes to move.
cld
stosb ; Set RString[0]. DI = ofs Rstring[1].
jcxz BDone ; anything to move now?
add di, dx ; es:di => RString[dl]
mov dl, al ; update length
shr cx, 1
rep movsw ; Move cx words.
rcl cx, 1
rep movsb ; Move odd byte, if any.
BDone: pop ds ; Restore RF segment.
mov ax, [bx].BufES ; Restore Buffer segment.
mov es, ax
ret
BufMove ENDP
;----------------------------------------------------------------------
; Fill disk buffer. Read RF.BSize bytes from file RF.Handle to ES:[BufStart].
; On last buffer, last ^Z is stripped.
; Inputs:
; DS:BX must point to RFrec.
; ES must point to Buffer segment. ( RF.BufES )
;
; If Failed, returns carry flag set, reason in AX:
; a) if a DOS error occurs, the DOS Error code is returned in ax.
; b) if end of file (0 bytes left to read), AX is set to $FFFF
;
; If Successful, returns carry flag clear and:
; a) di points to buffer start.
; b) cx = number of bytes read.
;
; AX Error code if failed BX restored CX = Bytes read DX restored
; DS restored SI destroyed ES unaffected DI = Buffer start
;
FillBuf PROC NEAR
mov si, dx ; save Line length
mov cx, [bx].BSize
mov dx, [bx].BufStart ; point ds:DX to offset of buffer.
mov di, dx ; (reset BufDI for later)
mov bx, [bx].Handle ; bx = Handle
mov ax, es
mov ds,ax ; set DS:dx
mov ah, 3fh ; DOS read file function.
int 21h
mov dx, si ; restore Line Length
lds bx, RF ; restore RFrec address
jc GetOut ; BlockRead error?
xchg cx, ax ; ax = bytes to read. cx = bytes read.
jcxz EOF ; if no bytes read, we're done
mov [bx].TotRead, cx ; store number bytes read.
inc [bx].NBufs ; update file position
cmp cx, ax ; is this last buffer?
je GetOut ; if not, we're done.
mov si, di ; else check for ^Z
add si, cx ; use si as index.
cmp byte ptr es:[si-1], 26 ; end of buffer a ^Z?
jne NoCtrlZ ; no, go on.
dec cx ; yes. Dec bytes read.
dec [bx].TotRead
jcxz EOF ; if cx = 0 then EOF
NoCtrlZ: clc ; Return success.
jmp short GetOut
EOF: mov ax, 0FFFFh ; set result to EOF
stc ; Return failure.
GetOut: ret
FillBuf ENDP
;************* The following PROCs ARE PUBLIC and FAR *************
;-------------------------------------------------------------------------
; Function FOpen(Fn : String;
; DBsize : Word;
; VAR BufP) : Word;
; Returns 0 on success, DOS error on failure.
Fn EQU dword ptr [bp+16] ; address of filename
DBsize EQU word ptr [bp+14] ; requested size of buffer
BufP EQU dword ptr [bp+10] ; Ofs of Buffer
rfr equ dword ptr [bp+6] ; address of rfrec record
rfrec@FOpen PROC FAR
push bp
mov bp,sp
push ds ; save turbo's DS
les di, RfR ; es:di points to RFrec.
mov si, di ; save RF offset
xor ax, ax ; fill RFrec fields with 0.
mov cx, RFWordSize ; CX = #words to fill
rep stosw
mov di, si ; Restore RF offset
cmp DBsize, ax ; Is requested buffer size > 0
jnz BSizeOK ; Yes.
mov ax, 12 ; No. Return invalid file access code.
jmp short OpenDone
BSizeOK: ; make filename asciiz
lds si, Fn ; point to Fn[0]
mov bl, [si]
xor bh, bh ; bx = length(Fn)
inc si ; si = offset of Fn[1]
mov [si+bx], al ; Fn[Length(Fn)+1] := 0.
mov dx, si ; ds:dx => Filename[1]
mov ax,3d00h ; ax=3D00, open file, read access
int 21h
jc OpenDone ; if DOS error, return with code in AX
mov es:[di].Handle, ax ; else set RFrec.Handle,
mov ax, DBsize ; and buffer size,
mov es:[di].BSize, ax
lds si, BufP ; and RF Buffer address.
mov es:[di].BufStart, si
mov ax, ds
mov es:[di].BufES, ax
xor ax,ax ; and return success.
OpenDone: pop ds ; restore Turbo DS
mov sp,bp
pop bp
ret 14
rfrec@FOpen ENDP
;-------------------------------------------------------------------------
; Procedure FClose;
; Closes Handle if BSize > 0 and Handle > 4
; frec dword [bp+6]
rfrec@FClose PROC FAR
push bp
mov bp,sp
les di,[bp+6] ; ES:DI points to RFrec
xor ax,ax ; AX = 0.
cmp es:[di].BSize, ax ; Had it been opened?
jz DoneClose ; No, get out.
mov es:[di].BSize, ax
mov es:[di].BufCX, ax
mov bx, es:[di].Handle ; BX = RF.Handle
mov es:[di].Handle, ax ; RF.Handle = 0
cmp bx, 4 ; If attempting to close
jbe DoneClose ; standard DOS device, DON'T.
mov ah,3eh ; DOS close file function
int 21h
DoneClose: mov sp,bp
pop bp
ret 4
rfrec@FClose ENDP
;-------------------------------------------------------------------------
; Function FReadLn(VAR RString : String) : Word;
;
; rstring dword [pb+10]
; rfrec dword [bp+6]
; If successful:
; Returns 0.
; RString = string read.
; If failed:
; Returns either DOS error code
; or $FFFF if EOF.
;
; Calls: FillBuf, BufMove.
rfrec@FReadLn PROC FAR
cld ; forward string operations.
push bp ; set up pascal stack frame.
mov bp,sp
push ds ; save turbo's DS
xor dx, dx ; dx = line length
mov cx, dx ; cx = 0.
lds bx, RF ; ds:bx points to RFrec
mov di, [bx].BufDI ; DI = Buffer offset.
mov ax, [bx].BufES
mov es, ax ; ES:DI points to buffer.
or cx, [bx].BufCX ; CX = number bytes left to scan for.
jnz Scan ; if > 0 then scan
call FillBuf ; else fill the buffer.
jc Done ; If error, then get out.
Scan: push di ; save original buffer position
push cx ; save numbytes to scan for
mov al, 13 ; scan for CR
repne scasb
pop ax ; ax = numbytes before scasb
jz Found
; wasn't found. Restore old DI and CX for Bufmove.
pop di ; restore di for BufMove.
mov cx, ax ; restore cx.
call BufMove ; move results to RString, and
call FillBuf ; fill the buffer
jnc Scan ; If no error, then keep searching.
; Either EOF or DOS error occurred.
cmp dl, 0 ; Length(RString) = 0?
je Done ; Yes, return FillBuf Error.
; else report no error because some
xor ax, ax ; chars have already been moved.
mov [bx].BufCX, ax ; Force FillBuf call next time.
jmp short done
Found: ; ^M was found.
mov [bx].BufDI, di ; Set up RFrec for next time.
mov [bx].BufCX, cx
pop di ; Found so get old DI from stack.
sub ax, cx ; Set up to move to RString.
dec ax
mov cx, ax
call BufMove
xor ax, ax ; set return code = 0.
Done: pop ds ; Restore everything and return.
mov sp,bp
pop bp
ret 8
rfrec@FReadLn ENDP
;-------------------------------------------------------------------------
; Function FRead(VAR Ch : Char) : Word;
; If successful:
; Returns 0.
; Ch = Character read from file.
; All ctrl chars pass, except last ^Z in file, if there is one.
; If failed:
; Returns either DOS error code
; or $FFFF if EOF.
;
rfrec@FRead PROC FAR
cld ; all forward string operations.
push bp ; set up pascal stack frame.
mov bp,sp
mov dx, ds ; save turbo's DS
lds bx, rf ; DS:BX points to RFrec
mov di, [bx].BufDI ; DI = Buffer offset.
mov cx, [bx].BufCX ; CX = number of bytes left.
mov ax, [bx].BufES
mov es, ax ; ES:DI points to buffer.
jcxz @ReCall
jmp short StoreIt
@ReCall: call FillBuf ; Fill the buffer
jc @Done ; If error or EOF, then exit.
StoreIt: dec cx ; the character is in ES:DI
mov [bx].BufCX, cx ; Set up RFrec for next time.
mov al, es:[di] ; AL = the character.
inc di
mov [bx].BufDI, di
; set VAR Ch and result.
les di, RCh
stosb
xor ax, ax ; set return code.
@Done: mov ds, dx ; Restore everything and return.
mov sp,bp
pop bp
ret 8
rfrec@FRead ENDP
;-------------------------------------------------------------------------
; Function FSeek(FPo : LongInt) : Word;
; Seeks to FPo and fills buffer.
; returns 0 if success
; else returns dos error code.
;
; fpo word bp+10
; self dword pb+6
rfrec@FSeek PROC FAR
push bp ; set up pascal stack frame.
mov bp,sp
push ds ; save turbo's DS
lds si, RF ; ds:si points to RFrec
; set up and divide to find buffer number and offset.
mov cx, [si].BSize ; CX = buffer size.
jcxz DivZero ; Avoid divide by zero error
jmp short Divide
DivZero: mov ax, 200 ; return TP divide by zero error code.
jmp short DoneFSeek
;Divide: ; load AX:DX with FPo
divide: mov ax, [bp+10]
mov dx, [bp+12]
div cx ; calculate the required block number
inc ax ; adjust for one-based NBufs
; BufferNumber is now in AX, Offset in DX
cmp [si].NBufs, ax ; current NBufs = one we're looking for?
jne FillerUp ; no, gotta read it.
cmp [si].TotRead, 0 ; yes. Is TotRead in the buffer > 0?
jz FillerUp ; yes. read it from disk.
jmp short Filled
FillerUp: ; Move DOS file pointer and fill buffer.
push dx ; save file buffer offset to seek to.
dec ax ; adjust BufferNumber for zero base.
mov [si].NBufs, ax
xor dx, dx ; prepare to multiply.
mul [si].BSize
mov bx, [si].Handle
mov cx, ax ; load CX:DX with FPo
xchg cx, dx
mov ax, 4200h ; DOS move file pointer function.
int 21h
pop dx
jc DoneFSeek ; If DOS error, get out.
; Successful seek. Now set up to refill buffer.
mov ax, [si].BufES ; ES = Buffer segment
mov es, ax
mov bx, si ; BX = RFrec offset.
call FillBuf
mov si, bx
jc DoneFSeek ; If DOS error, then get out
Filled: ; Buffer is filled.
; NBufs is set to proper BufferNumber.
; dx = offset in buffer.
; Adjust RFrec to point to proper position.
; set BufCX for next scan.
mov ax, [si].TotRead ; AX = Total bytes in buffer.
cmp ax, dx ; Is dx past end of file?
ja InBuffer ; yes, set BufCX
mov ax, 100 ; set result to Read Error.
jmp short DoneFSeek
InBuffer: sub ax, dx
mov [si].BufCX, ax
; set BufDI for next scan.
mov ax, [si].BufStart ; AX = Starting offset of buffer.
add ax, dx ; add offset in buffer to seek to.
mov [si].BufDI, ax
xor ax, ax ; return success.
DoneFSeek: pop ds
mov sp,bp
pop bp
ret 8
rfrec@FSeek ENDP
;-------------------------------------------------------------------------
CODE ENDS
END