2.11BSD/src/lib/libc/pdp/stdio/fgets.s
/*
* Copyright (c) 1987 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#ifdef LIBC_SCCS
<@(#)fgets.s 5.6 (Berkeley) 9/2/88\0>
.even
#endif LIBC_SCCS
#include "DEFS.h"
#include "STDIO.h"
.globl __filbuf
#define S r4
#define IOP r3
#define COUNT r2
#define P r1
#define C r0
/*
* P & C get trounced when we call someone else ...
*/
/*
* char *fgets(s, n, iop);
* char *s;
* int n;
* FILE *iop;
*
* arguments: a target string, a length, and a file pointer.
* side effects: reads up to and including a newline, or up to n-1 bytes,
* whichever is less, from the file indicated by iop into the target
* string and null terminates.
* result: the target string if successful, 0 otherwise.
*/
ENTRY(fgets)
mov r2,-(sp) / need a few registers
mov r3,-(sp)
mov r4,-(sp)
# define OLD_S 8.(sp)
mov OLD_S,S / grab string pointer
mov 10.(sp),COUNT / string length
mov 12.(sp),IOP / and I/O pointer
/*
* Sanity check -- is the string big enough? Has to hold at least
* a null ...
*/
dec COUNT / We scan at most n-1 characters
ble Lerror
/*
* If no characters, call _filbuf() to get some.
*/
tst _CNT(IOP)
bgt Lscan
Lloop:
mov IOP,-(sp) / _filbuf(stdin)
jsr pc,__filbuf
tst (sp)+
tst r0 / _filbuf return EOF?
blt Leof
movb r0,(S)+ / save the returned character
dec COUNT / out of space?
ble 1f
cmpb r0,$NL / a newline?
bne 2f
1:
clrb (S) / yes, terminate the string and return
br Lret / with a pointer to it
2:
tst _BASE(IOP) / is input buffered?
beq Lloop / no, have to do it the hard way ...
tst _CNT(IOP) / did __filbuf leave us anything
beq Lloop / to work with??
Lscan:
/*
* Copy till terminating newline found or end of buffer or end of
* string.
*/
mov _PTR(IOP),P / grab pointer into I/O buffer
mov _CNT(IOP),C / and how many characters in it
sub C,COUNT / more in buffer than we can take?
bge 1f
add COUNT,C / only copy till end of string then
clr COUNT
1:
movb (P),(S)+ / copy from buffer to string
cmpb (P)+,$NL / was it a newline?
beq 2f
sob C,1b / repeat till we run out ...
tst COUNT / more room in string?
bne Lloop / yes, go back for another buffer
2:
clrb (S) / terminate string
sub _PTR(IOP),P / figure out how much we took from
add P,_PTR(IOP) / the buffer and update IOP
sub P,_CNT(IOP)
Lret:
mov OLD_S,r0 / return pointer to string
Lexit:
mov (sp)+,r4 / restore registers
mov (sp)+,r3
mov (sp)+,r2
rts pc / and return
/*
* End of file? Check to see if we copied any data.
*/
Leof:
cmp S,OLD_S / did we copy anything?
beq Lerror / nope, return null
clrb (S) / yes, terminate string
br Lret / and return a pointer to it
/*
* Error/eof return -- null pointer.
*/
Lerror:
clr r0
br Lexit