Category : C++ Source Code
Archive   : VCCRT2.ZIP
Filename : FGETS.ASM

 
Output of file : FGETS.ASM contained in archive : VCCRT2.ZIP
page ,132
title fgets - read a string from a stream
;***
;fgets.asm - read a string from a stream
;
; Copyright (c) 1988-1992, Microsoft Corporation. All rights reserved.
;
;Purpose:
; Defines fgets() - read a string from a stream
;
;*******************************************************************************


.xlist
include version.inc
include cmacros.inc
include stdio.inc
include os2dll.inc
.list

externP _filbuf ; fill stream buffer



sBegin data
assumes ds,data

externW _iob

sEnd data


sBegin code
assumes cs,code
assumes ds,data

;***
;char *fgets( char *string, int count, FILE *stream ) - read a string of
; characters from 'stream' into 'string'.
;
;Purpose:
; Read characters from the specified stream, into the specified buffer,
; until count - 1 characters have been read, a newline is read or eof
; is hit (whichever occurs first). Then, append a null character ('\0')
; to string of characters and return. Note that, if read, the newline
; character IS placed in the user's buffer. Note that if eof is found
; immediately, the user's buffer is not modified and NULL is returned.
;
;Entry:
; string - pointer to buffer to hold the input characters
; count - maximum number of characters, including the terminating
; newline, to be placed in the buffer (i.e., one more than
; the maximum number of characters to be read)
; stream - stream to read the characters from
;
;Exit:
; if count == 0, or an error occurs or eof is encountered immediately
; then
; return NULL
; else
; return string
;
;*******************************************************************************

cProc fgets,,

parmDP string
parmW count
parmDP stream

cBegin

ifdef _LOAD_DGROUP
push ds
mov ax,DGROUP
mov ds,ax
endif ;_LOAD_DGROUP


;**
; Initialize dx to count - 1. Also, check for special case of count <= 0.

mov dx,count ; dx = count
or dx,dx
jle retnull
dec dx ; dx = count - 1

;**
; Set:
; ds:bx = stream (except for MTHREAD case)
; es:di = string

mov bx,word ptr [stream] ; ds:bx = stream pointer

if sizeD
les di,[string] ; es:di = caller's buffer
else
push ds
pop es
mov di,[string] ; es:di = caller's buffer
endif

loopbegin:

;**
; Test the number of characters to be read. If 0, we're done (except for
; adding the null character and setting up the return).

or dx,dx
jz appendnull

;**
; Check to see if the stream buffer is empty. If not, process the characters
; in the buffer.

mov cx,[bx]._cnt
jcxz dofilbuf

cmp cx,dx ; set cx = min of the number of chars...
jbe get_ptr ; ...in the stream buffer and the...
mov cx,dx ; ...number of chars to be read

get_ptr:

if sizeD
push ds ; save DGROUP
lds si,[bx]._ptr ; ds:si = pointer to stream buffer
assumes ds,nothing
else
mov si,[bx]._ptr ; ds:si = pointer to stream buffer
endif

mov ah,0Ah ; ah = linefeed character
push cx ; save number of chars

even

nextchar:
lodsb ; get a byte

stosb ; place in user's buffer
cmp al,ah ; was it a linefeed?
loopne nextchar
pop ax ; ax = loop entry value of cx

if sizeD
pop ds ; restore DGROUP
assumes ds,data
endif

mov word ptr [bx]._ptr,si ; update stream pointer
je foundlf

sub [bx]._cnt,ax ; update stream count
sub dx,ax ; update number of chars to read in
jmp short loopbegin

; Call _filbuf to fill it up the stream buffer and process the single
; character returned by _filbuf. Note that in the case of single character
; buffering (aka no input buffering at all), the stream buffer will be
; empty again after the call to _filbuf so that the we end up doing
; character-at-a-time processing (as we should).

dofilbuf:
push es ; save registers
push bx
push dx

if sizeD
push ds ; push arg
push bx
else
push bx ; push arg
endif

callcrt _filbuf ; _filbuf(stream)

if sizeD
add sp,4 ; clean off arg
else
pop dx ; clean off arg
endif

pop dx ; restore saved regs
pop bx
pop es

cmp ax,EOF ; are we at end-of-file?
je ateof ; yes
stosb ; put the char in the user's buffer
cmp al,0Ah ; was it a linefeed (aka newline)
je appendnull ; yes
dec dx ; update number of chars to read
jmp short loopbegin

ateof:
cmp di,word ptr [string] ; have we read in anything yet?
je retnull ; no, go return a NULL
test [bx]._flag,_IOERR ; did an error occur?
jz appendnull ; no, do a normal return
; fall thru

retnull:
xor ax,ax
if sizeD
cwd
endif
jmp short done

foundlf:
sub ax,cx ; number of chars copied over
sub [bx]._cnt,ax ; update stream count

appendnull:
xor ax,ax
stosb

mov ax,word ptr [string]

if sizeD
mov dx,word ptr [string+2]
endif

done:


ifdef _LOAD_DGROUP
pop ds
endif ;_LOAD_DGROUP

cEnd

sEnd code
end


  3 Responses to “Category : C++ Source Code
Archive   : VCCRT2.ZIP
Filename : FGETS.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/