1/* 2 * Copyright (c) 1985 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that this notice is preserved and that due credit is given 7 * to the University of California at Berkeley. The name of the University 8 * may not be used to endorse or promote products derived from this 9 * software without specific written prior permission. This software 10 * is provided ``as is'' without express or implied warranty. 11 */ 12 13#ifdef LIBC_SCCS 14_sccsid:.asciz "@(#)fgets.s 5.4 (Berkeley) 05/23/88" 15#endif /* LIBC_SCCS */ 16 17/* 18 * char *fgets(s, n, iptr); 19 * char *s; 20 * int n; 21 * FILE *iptr; 22 * 23 * arguments: a target string, a length, and a file pointer. 24 * side effects: reads up to and including a newline, or up to n-1 bytes, 25 * whichever is less, from the file indicated by iptr into the target 26 * string and null terminates. 27 * result: the target string if successful, 0 otherwise. 28 */ 29 30#include "DEFS.h" 31 32#define NL 0xa 33 34ENTRY(fgets, R11|R10|R9) 35 36#define OLD_S 4(ap) 37#define S r11 38 movl OLD_S,S 39 40#define N 8(ap) 41 42#define IPTR r10 43#define _CNT 44#define _PTR 4 45#define _BASE 8 46 movl 12(ap),IPTR 47 48#define COUNT r9 49 50 /* 51 * Sanity check -- is the buffer big enough? 52 */ 53 cmpl N,$1 54 jleq Lerror 55 56 subl3 $1,N,COUNT /* We scan at most COUNT chars */ 57 58 /* 59 * If no characters, call _filbuf() to get some. 60 */ 61 tstl _CNT(IPTR) 62 jgtr Lscan 63 64Lloop: 65 pushl IPTR 66 calls $1,__filbuf 67 tstl r0 68 jlss Leof 69 movb r0,(S)+ /* Save the returned character */ 70 decl N 71 decl COUNT 72 jleq 1f 73 cmpb r0,$NL /* If it was a newline, we're done */ 74 jneq 2f 751: 76 clrb (S) 77 jbr Lret 782: 79 tstl _BASE(IPTR) /* Is the input buffered? */ 80 jeql Lloop /* If not, loop inefficiently */ 81 82 /* 83 * Look for a newline in the buffer. 84 */ 85Lscan: 86 cmpl _CNT(IPTR),COUNT /* Is buffer bigger than N-1? */ 87 jgeq 1f 88 movl _CNT(IPTR),COUNT /* If not, don't read off the end */ 891: 90 locc $NL,COUNT,*_PTR(IPTR) /* Scan the buffer */ 91 jeql Lagain 92 93 /* 94 * Success -- copy the data and return. 95 */ 96 decl r0 /* How many characters did we read? */ 97 subl2 r0,COUNT 98 movc3 COUNT,*_PTR(IPTR),(S) /* Copy the data */ 99 clrb (r3) 100 subl2 COUNT,_CNT(IPTR) /* Fix up the I/O buffer */ 101 movl r1,_PTR(IPTR) 102 103Lret: 104 movl OLD_S,r0 105 ret 106 107 /* 108 * If we run out of characters, copy the buffer and loop if needed. 109 */ 110Lagain: 111 movc3 COUNT,*_PTR(IPTR),(S) /* Copy the data */ 112 subl2 COUNT,_CNT(IPTR) /* Adjust the buffers and counts */ 113 movl r1,_PTR(IPTR) 114 subl2 COUNT,N 115 movl r3,S 116 subl3 $1,N,COUNT 117 jgtr Lloop 118 119 /* 120 * End of file? Check to see if we copied any data. 121 */ 122Leof: 123 cmpl S,OLD_S 124 jeql Lerror 125 clrb (S) 126 jbr Lret 127 128 /* 129 * Error return -- null pointer. 130 */ 131Lerror: 132 clrl r0 133 ret 134