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 #define NDEBUG 28 #include <assert.h> 29 30 #if STDC_HEADERS 31 #include <stdlib.h> 32 #else 33 char *malloc (), *realloc (); 34 #endif 35 36 /* Always add at least this many bytes when extending the buffer. */ 37 #define MIN_CHUNK 64 38 39 /* Read up to (and including) a TERMINATOR from STREAM into *LINEPTR 40 + OFFSET (and null-terminate it). *LINEPTR is a pointer returned from 41 malloc (or NULL), pointing to *N characters of space. It is realloc'd 42 as necessary. Return the number of characters read (not including the 43 null terminator), or -1 on error or EOF. */ 44 45 int 46 getstr (lineptr, n, stream, terminator, offset) 47 char **lineptr; 48 size_t *n; 49 FILE *stream; 50 char terminator; 51 int offset; 52 { 53 int nchars_avail; /* Allocated but unused chars in *LINEPTR. */ 54 char *read_pos; /* Where we're reading into *LINEPTR. */ 55 int ret; 56 57 if (!lineptr || !n || !stream) 58 return -1; 59 60 if (!*lineptr) 61 { 62 *n = MIN_CHUNK; 63 *lineptr = malloc (*n); 64 if (!*lineptr) 65 return -1; 66 } 67 68 nchars_avail = *n - offset; 69 read_pos = *lineptr + offset; 70 71 for (;;) 72 { 73 register int c = getc (stream); 74 75 /* We always want at least one char left in the buffer, since we 76 always (unless we get an error while reading the first char) 77 NUL-terminate the line buffer. */ 78 79 assert(*n - nchars_avail == read_pos - *lineptr); 80 if (nchars_avail < 2) 81 { 82 if (*n > MIN_CHUNK) 83 *n *= 2; 84 else 85 *n += MIN_CHUNK; 86 87 nchars_avail = *n + *lineptr - read_pos; 88 *lineptr = realloc (*lineptr, *n); 89 if (!*lineptr) 90 return -1; 91 read_pos = *n - nchars_avail + *lineptr; 92 assert(*n - nchars_avail == read_pos - *lineptr); 93 } 94 95 if (c == EOF || ferror (stream)) 96 { 97 /* Return partial line, if any. */ 98 if (read_pos == *lineptr) 99 return -1; 100 else 101 break; 102 } 103 104 *read_pos++ = c; 105 nchars_avail--; 106 107 if (c == terminator) 108 /* Return the line. */ 109 break; 110 } 111 112 /* Done - NUL terminate and return the number of chars read. */ 113 *read_pos = '\0'; 114 115 ret = read_pos - (*lineptr + offset); 116 return ret; 117 } 118 119 int 120 getline (lineptr, n, stream) 121 char **lineptr; 122 size_t *n; 123 FILE *stream; 124 { 125 return getstr (lineptr, n, stream, '\n', 0); 126 } 127