1 /*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Chris Torek. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #if defined(LIBC_SCCS) && !defined(lint) 12 static char sccsid[] = "@(#)fgetln.c 5.2 (Berkeley) 05/04/91"; 13 #endif /* LIBC_SCCS and not lint */ 14 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <string.h> 18 #include "local.h" 19 20 /* 21 * Expand the line buffer. Return -1 on error. 22 * The `new size' does not account for a terminating '\0', 23 * so we add 1 here. 24 */ 25 __slbexpand(fp, newsize) 26 FILE *fp; 27 size_t newsize; 28 { 29 void *p; 30 31 if (fp->_lb._size >= ++newsize) 32 return (0); 33 if ((p = realloc(fp->_lb._base, newsize)) == NULL) 34 return (-1); 35 fp->_lb._base = p; 36 fp->_lb._size = newsize; 37 return (0); 38 } 39 40 /* 41 * Get an input line. The returned pointer often (but not always) 42 * points into a stdio buffer. Fgetline smashes the newline (if any) 43 * in the stdio buffer; callers must not use it on streams that 44 * have `magic' setvbuf() games happening. 45 */ 46 char * 47 fgetline(fp, lenp) 48 register FILE *fp; 49 size_t *lenp; 50 { 51 register unsigned char *p; 52 register size_t len; 53 size_t off; 54 55 /* make sure there is input */ 56 if (fp->_r <= 0 && __srefill(fp)) { 57 if (lenp != NULL) 58 *lenp = 0; 59 return (NULL); 60 } 61 62 /* look for a newline in the input */ 63 if ((p = memchr((void *)fp->_p, '\n', fp->_r)) != NULL) { 64 register char *ret; 65 66 /* 67 * Found one. Flag buffer as modified to keep 68 * fseek from `optimising' a backward seek, since 69 * the newline is about to be trashed. (We should 70 * be able to get away with doing this only if 71 * p is not pointing into an ungetc buffer, since 72 * fseek discards ungetc data, but this is the 73 * usual case anyway.) 74 */ 75 ret = (char *)fp->_p; 76 len = p - fp->_p; 77 fp->_flags |= __SMOD; 78 *p = 0; 79 fp->_r -= len + 1; 80 fp->_p = p + 1; 81 if (lenp != NULL) 82 *lenp = len; 83 return (ret); 84 } 85 86 /* 87 * We have to copy the current buffered data to the line buffer. 88 * 89 * OPTIMISTIC is length that we (optimistically) 90 * expect will accomodate the `rest' of the string, 91 * on each trip through the loop below. 92 */ 93 #define OPTIMISTIC 80 94 95 for (len = fp->_r, off = 0;; len += fp->_r) { 96 register size_t diff; 97 98 /* 99 * Make sure there is room for more bytes. 100 * Copy data from file buffer to line buffer, 101 * refill file and look for newline. The 102 * loop stops only when we find a newline. 103 */ 104 if (__slbexpand(fp, len + OPTIMISTIC)) 105 goto error; 106 (void) bcopy((void *)fp->_p, (void *)(fp->_lb._base + off), 107 len - off); 108 off = len; 109 if (__srefill(fp)) 110 break; /* EOF or error: return partial line */ 111 if ((p = memchr((void *)fp->_p, '\n', fp->_r)) == NULL) 112 continue; 113 114 /* got it: finish up the line (like code above) */ 115 fp->_flags |= __SMOD; /* soon */ 116 diff = p - fp->_p; 117 len += diff; 118 if (__slbexpand(fp, len)) 119 goto error; 120 (void) bcopy((void *)fp->_p, (void *)(fp->_lb._base + off), 121 diff); 122 fp->_r -= diff + 1; 123 fp->_p = p + 1; 124 break; 125 } 126 if (lenp != NULL) 127 *lenp = len; 128 fp->_lb._base[len] = 0; 129 return ((char *)fp->_lb._base); 130 131 error: 132 if (lenp != NULL) 133 *lenp = 0; /* ??? */ 134 return (NULL); /* ??? */ 135 } 136