home *** CD-ROM | disk | FTP | other *** search
- ; 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