home *** CD-ROM | disk | FTP | other *** search
- title stream i/o
- include asm.inc
-
- public fclose
- public fopen
- public fread
- public fwrite
-
- SIO_BUFSIZ equ 8192 ; stream io buffer size
-
- stream_io_str struc
- sio_position dd ? ; stream position
- sio_offset dd ? ; buffer offset
- sio_read_bc dw ? ; buffer byte count for reading
- sio_write_bc dw ? ; buffer byte count for writing
- sio_file_handle dw ? ; dos file handle
- sio_buffer db SIO_BUFSIZ dup(?) ; stream buffer
- stream_io_str ends
-
-
- .data
- extb ertx_disk_full
- ertx_fopen_mode db 'Bad mode in fopen',0
- ertx_out_of_handles db 'Out of stream handles',0
- ertx_stream_handle db 'Bad stream handle',0
-
- .data?
- stream_pointers dd FOPEN_MAX dup(?)
-
-
- .code
- extn free,ms_dos,ms_dos_strerror,set_strerror,malloc
-
-
- ;; fclose
- ;
- ; entry BX stream handle
- ; exit Cf if error closing file or bad handle
- ; uses AX,BX
- ;
- fclose proc
- pushm di,si,es
- call fwrite_flush ; write bytes left in stream buffer
- jc fcl1 ; if disk full
-
- call stream_struct_write ; access stream structure
- jc fcl1 ; if bad handle
-
- mov si,bx ; clear stream structure pointer
- add si,si
- add si,si
- mov wptr stream_pointers[bp+si],NULL_POINTER
- mov wptr stream_pointers[bp+si+2],NULL_POINTER
-
- mov bx,es:sio_file_handle[di]
- call free
-
- mov ah,3Eh
- call ms_dos_strerror
-
- fcl1: popm es,si,di
- ret
- fclose endp
-
-
- ;; fopen
- ;
- ; entry AX mode, 'r' or 'w' to open for reading or writing
- ; DS:SI filename
- ; exit BX stream handle
- ; Cf if error
- ; uses AX
- ;
- fopen proc
- pushm cx,dx,di,es
- cmp ax,'r'
- mov dx,3D00h
- je fop1 ; if opening file for reading only
- cmp ax,'w'
- jne fop3 ; if not open for write (unknown mode)
- mov dh,3Ch
- mov cx,0
- fop1: mov ax,dx
- mov dx,si
- call ms_dos_strerror ; (ms dos with error handling)
- jc fop2 ; if file open failed
- mov dx,ax
-
- call malloc_stream
- jc fop4 ; if no memory or stream handles
-
- mov al,0 ; zero stream structure (except for
- mov cx,sio_buffer ; buffer space)
- push di
- rep stosb
- pop di
-
- mov es:sio_file_handle[di],dx
- clc
- fop2: popm es,di,dx,cx
- ret
-
- fop3: lea ax,ertx_fopen_mode ; *Bad mode in fopen*
- call set_strerror
- jmp fop2
-
- fop4: mov ah,3Eh ; close file, no memory for structure
- mov bx,dx
- call ms_dos
- stc
- jmp fop2
- fopen endp
-
-
- ;; fread
- ;
- ; entry BX stream handle
- ; CX byte count
- ; ES:DI destination pointer
- ; exit AX actual byte count (!=CX for EOF)
- ; DI updated
- ; Cf if error
- ;
- fread proc
- pushm di,bx,cx,dx,si,ds
- cmp bx,stdin
- je fre3 ; if special handle, standard input
-
- call stream_struct_read
- jc fre4
- mov bx,si
-
- fre1: jcxz fre4 ; if read finished
-
- mov ax,wptr sio_position[bx]; compute stream position w/i buffer
- mov dx,wptr sio_position[bx+2]
- sub ax,wptr sio_offset[bx]
- sbb dx,wptr sio_offset[bx+2]
- jnz fre2 ; if buffer not w/i 64k of position
-
- mov dx,sio_read_bc[bx] ; get number of bytes to end of buffer
- sub dx,ax
- jbe fre2 ; if stream position not in buffer
-
- lea si,sio_buffer[bx]
- add si,ax
-
- call rep_movsb_limit
-
- add wptr sio_position[bx],dx ; update stream position
- adc wptr sio_position[bx+2],0
- jmp fre1
-
- fre2: call fread_primitive ; fill stream buffer
- jbe fre4 ; if error (Cf==1) or EOF (Zf==1)
- jmp fre1 ; else successful
-
- fre3: mov ah,3Fh ; read from special handle stdin
- mov dx,es
- mov ds,dx
- mov dx,di
- call ms_dos_strerror
- jc fre4
-
- add di,ax ; (should not set Cf unless DI wraps)
-
- fre4: popm ds,si,dx,cx,bx,ax
- jc fre5 ; if error
- neg ax ; else return bytes read
- add ax,di
- clc
- fre5: ret
- fread endp
-
-
- ;; fread primitive
- ;
- ; entry DS:BX stream structure
- ; exit AX bytes read from file
- ; Cf if error (Zf unknown)
- ; Zf if end of file
- ; uses SI
- ;
- fread_primitive proc
- pushm bx,cx,dx
- mov si,bx
-
- mov ax,4200h ; position file
- mov bx,sio_file_handle[si]
- mov dx,wptr sio_position[si]
- mov cx,wptr sio_position[si+2]
- call ms_dos_strerror
- jc frp1 ; if error position file
-
- mov wptr sio_offset[si],ax
- mov wptr sio_offset[si+2],dx
- mov sio_read_bc[si],0
-
- mov ah,3Fh ; read file
- mov cx,size sio_buffer
- lea dx,sio_buffer[si]
- call ms_dos_strerror
- jc frp1 ; if read error
- mov sio_read_bc[si],ax
-
- or ax,ax ; set Zf for end of file
- frp1: popm dx,cx,bx
- ret
- fread_primitive endp
-
-
- ;; fwrite
- ;
- ; entry BX stream handle
- ; CX byte count
- ; DS:SI source pointer
- ; exit AX bytes written
- ; SI updated
- ; Cf if error
- ;
- fwrite proc
- pushm si,cx,dx,di,es
- cmp bx,stdout ; check for special streams
- je fwr2 ; if writing to standard out
- cmp bx,stderr
- je fwr2 ; if writing to standard error
-
- call fwrite_flush_maybe ; flush buffer in event of seek
- jc fwr3 ; if bad handle or disk full
-
- call stream_struct_write ; access stream structure
- jc fwr3 ; if bad handle
-
- fwr1: clc
- jcxz fwr3 ; if write complete
-
- mov ax,es:sio_write_bc[di] ; compute space left in stream buffer
- mov dx,size sio_buffer
- sub dx,ax
- jb fwr3 ; if internal error (Cf=1)
-
- push di ; copy to stream buffer
- lea di,sio_buffer[di]
- add di,ax
- call rep_movsb_limit
- pop di
-
- add ax,dx ; update stream buffer byte count
- mov es:sio_write_bc[di],ax ; and position
- add wptr es:sio_position[di],dx
- adc wptr es:sio_position[di+2],0
-
- cmp ax,size sio_buffer ; check stream buffer level
- jb fwr1 ; if not full
- call fwrite_flush ; else write buffer to disk
- jnc fwr1 ; if write successful
- jmp fwr3 ; else disk full (Cf=1)
-
- fwr2: mov ah,40h ; write standard output/error
- mov dx,si
- call ms_dos_strerror
- jc fwr3 ; if write failed
- add si,ax
-
- fwr3: popm es,di,dx,cx,ax
- jc fwr4 ; if error
- neg ax ; else return bytes written
- add ax,si
- clc
- fwr4: ret
- fwrite endp
-
-
- ;; fwrite flush
- ;
- ; entry BX stream handle
- ; exit Cf if disk full, bad handle, or other error
- ; uses AX
- ;
- fwrite_flush proc
- pushm bx,cx,dx,si,ds
- call stream_struct_read
- jc fwf1 ; if bad handle
-
- mov cx,sio_write_bc[si]
- jcxz fwf1 ; if buffer empty (nothing to flush)
-
- mov ax,4200h ; position file
- mov bx,sio_file_handle[si]
- mov dx,wptr sio_offset[si]
- mov cx,wptr sio_offset[si+2]
- call ms_dos_strerror
- jc fwf1 ; if position failed
-
- mov ah,40h ; write file
- mov cx,sio_write_bc[si]
- lea dx,sio_buffer[si]
- call ms_dos_strerror
- jc fwf1 ; if write failed
-
- add wptr sio_offset[si],ax ; update buffer position
- adc wptr sio_offset[si+2],0
- mov sio_write_bc[si],0 ; clear output byte count
-
- cmp ax,cx
- je fwf1 ; if correct byte cnt written (Cf=0)
-
- lea ax,ertx_disk_full ; else *Disk full*
- call set_strerror
-
- fwf1: popm ds,si,dx,cx,bx
- ret
- fwrite_flush endp
-
-
- ;; fwrite flush maybe
- ;
- ; entry BX stream handle
- ; exit Cf if bad handle or disk full
- ; uses AX,DX
- ;
- fwrite_flush_maybe proc
- pushm si,ds
- call stream_struct_read
- jc ffm2 ; if bad stream handle
-
- mov ax,wptr sio_offset[si] ; compute buffer position
- mov dx,wptr sio_offset[si+2]
- add ax,sio_write_bc[si]
- adc dx,0
-
- cmp ax,wptr sio_position[si]
- jne ffm1 ; if wrong position
- cmp dx,wptr sio_position[si+2]
- je ffm2 ; if right position
-
- ffm1: call fwrite_flush
- jc ffm2 ; if disk full
-
- mov ax,wptr sio_position[si] ; reposition buffer
- mov wptr sio_offset[si],ax
- mov ax,wptr sio_position[si+2]
- mov wptr sio_offset[si+2],ax
-
- ffm2: popm ds,si
- ret
- fwrite_flush_maybe endp
-
-
- ;; malloc stream
- ;
- ; exit BX stream handle
- ; ES:DI stream structure
- ; Cf if no handles or memory left
- ; uses AX
- ;
- malloc_stream proc
- pushm cx,si
- mov bx,stderr ; find free stream handle
- mas1: inc bx
- cmp bx,FOPEN_MAX
- jae mas3 ; if no handles left
-
- mov si,bx
- add si,si
- add si,si
- les di,stream_pointers[bp+si]
- mov ax,es
- or ax,di
- jnz mas1 ; if stream allocated
-
- mov cx,size stream_io_str ; allocate memory for stream structure
- call malloc
- jc mas2 ; if no memory
-
- mov wptr stream_pointers[bp+si],di
- mov wptr stream_pointers[bp+si+2],es
-
- mas2: popm si,cx
- ret
-
- mas3: lea ax,ertx_out_of_handles ; *Out of stream handles*
- call set_strerror
- jmp mas2
- malloc_stream endp
-
-
- ;; rep movsb limit
- ;
- ; entry DS:SI source pointer
- ; ES:DI destination pointer
- ; CX byte count
- ; DX byte count limit
- ; exit SI,DI updated
- ; CX updated (nonzero if original DX<CX)
- ; DX actual number of bytes transfered (minimum of CX,DX)
- ;
- rep_movsb_limit proc
- push ax
- cmp cx,dx ; DX is unsigned minimum of CX and DX
- ja rmm1
- mov dx,cx
-
- rmm1: mov ax,cx ; this procedure implements a smart
- sub ax,dx ; "rep movsb" instruction. the
- mov cx,dx ; difference is it moves the minimum
- rep movsb ; number of bytes specified in CX or
- mov cx,ax ; DX. CX is updated normally; DX has
- pop ax ; the actual number of bytes moved.
- ret
- rep_movsb_limit endp
-
-
- ;; stream struct read
- ;
- ; entry BX stream handle
- ; exit DS:SI stream structure
- ; Cf if bad handle
- ; uses AX
- ;
- stream_struct_read proc
- cmp bx,FOPEN_MAX
- jae rss1 ; if handle too large
- mov si,bx
- add si,si
- add si,si
- lds si,stream_pointers[bp+si]
- mov ax,ds
- or ax,si
- jz rss1 ; if inactive stream
- ret
-
- rss1: lea ax,ertx_stream_handle ; *Bad stream handle*
- jmp set_strerror
- stream_struct_read endp
-
-
- ;; stream struct write
- ;
- ; entry BX stream handle
- ; exit ES:DI stream structure
- ; Cf if bad handle
- ; uses AX
- ;
- stream_struct_write proc
- cmp bx,FOPEN_MAX
- jae wss1 ; if handle too large
- mov di,bx
- add di,di
- add di,di
- les di,stream_pointers[bp+di]
- mov ax,es
- or ax,di
- jz wss1 ; if inactive stream
- ret
-
- wss1: lea ax,ertx_stream_handle ; *Bad stream handle*
- jmp set_strerror
- stream_struct_write endp
-
- end
-