1 /* getline.c -- Replacement for GNU C library function getline 2 3 Copyright (C) 1993 Free Software Foundation, Inc. 4 5 This program is free software; you can redistribute it and/or 6 modify it under the terms of the GNU General Public License as 7 published by the Free Software Foundation; either version 2 of the 8 License, or (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 18 19 /* Written by Jan Brittenson, bson@gnu.ai.mit.edu. */ 20 21 #ifdef HAVE_CONFIG_H 22 #include <config.h> 23 #endif 24 25 #include <sys/types.h> 26 #include <stdio.h> 27 #include <assert.h> 28 29 #if STDC_HEADERS 30 #include <stdlib.h> 31 #else 32 char *malloc (), *realloc (); 33 #endif 34 35 /* Always add at least this many bytes when extending the buffer. */ 36 #define MIN_CHUNK 64 37 38 /* Read up to (and including) a TERMINATOR from STREAM into *LINEPTR 39 + OFFSET (and null-terminate it). *LINEPTR is a pointer returned from 40 malloc (or NULL), pointing to *N characters of space. It is realloc'd 41 as necessary. Return the number of characters read (not including the 42 null terminator), or -1 on error or EOF. */ 43 44 int 45 getstr (lineptr, n, stream, terminator, offset) 46 char **lineptr; 47 size_t *n; 48 FILE *stream; 49 char terminator; 50 int offset; 51 { 52 int nchars_avail; /* Allocated but unused chars in *LINEPTR. */ 53 char *read_pos; /* Where we're reading into *LINEPTR. */ 54 int ret; 55 56 if (!lineptr || !n || !stream) 57 return -1; 58 59 if (!*lineptr) 60 { 61 *n = MIN_CHUNK; 62 *lineptr = malloc (*n); 63 if (!*lineptr) 64 return -1; 65 } 66 67 nchars_avail = *n - offset; 68 read_pos = *lineptr + offset; 69 70 for (;;) 71 { 72 register int c = getc (stream); 73 74 /* We always want at least one char left in the buffer, since we 75 always (unless we get an error while reading the first char) 76 NUL-terminate the line buffer. */ 77 78 assert((*lineptr + *n) == (read_pos + nchars_avail)); 79 if (nchars_avail < 2) 80 { 81 if (*n > MIN_CHUNK) 82 *n *= 2; 83 else 84 *n += MIN_CHUNK; 85 86 nchars_avail = *n + *lineptr - read_pos; 87 *lineptr = realloc (*lineptr, *n); 88 if (!*lineptr) 89 return -1; 90 read_pos = *n - nchars_avail + *lineptr; 91 assert((*lineptr + *n) == (read_pos + nchars_avail)); 92 } 93 94 if (c == EOF || ferror (stream)) 95 { 96 /* Return partial line, if any. */ 97 if (read_pos == *lineptr) 98 return -1; 99 else 100 break; 101 } 102 103 *read_pos++ = c; 104 nchars_avail--; 105 106 if (c == terminator) 107 /* Return the line. */ 108 break; 109 } 110 111 /* Done - NUL terminate and return the number of chars read. */ 112 *read_pos = '\0'; 113 114 ret = read_pos - (*lineptr + offset); 115 return ret; 116 } 117 118 int 119 getline (lineptr, n, stream) 120 char **lineptr; 121 size_t *n; 122 FILE *stream; 123 { 124 return getstr (lineptr, n, stream, '\n', 0); 125 } 126