1 /* getline.c -- Replacement for GNU C library function getline 2 3 Copyright (C) 1993, 1996, 2001, 2002 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 18 19 /* Written by Jan Brittenson, bson@gnu.ai.mit.edu. */ 20 21 #include <assert.h> 22 #include <stdio.h> 23 24 /* Always add at least this many bytes when extending the buffer. */ 25 #define MIN_CHUNK 64 26 27 /* Read up to (and including) a TERMINATOR from STREAM into *LINEPTR 28 + OFFSET (and null-terminate it). *LINEPTR is a pointer returned from 29 malloc (or NULL), pointing to *N characters of space. It is realloc'd 30 as necessary. Return the number of characters read (not including the 31 null terminator), or -1 on error or EOF. 32 NOTE: There is another getstr() function declared in <curses.h>. */ 33 static int getstr(char **lineptr, size_t *n, FILE *stream, 34 char terminator, size_t offset) 35 { 36 int nchars_avail; /* Allocated but unused chars in *LINEPTR. */ 37 char *read_pos; /* Where we're reading into *LINEPTR. */ 38 int ret; 39 40 if (!lineptr || !n || !stream) 41 return -1; 42 43 if (!*lineptr) { 44 *n = MIN_CHUNK; 45 *lineptr = malloc(*n); 46 if (!*lineptr) 47 return -1; 48 } 49 50 nchars_avail = *n - offset; 51 read_pos = *lineptr + offset; 52 53 for (;;) { 54 register int c = getc(stream); 55 56 /* We always want at least one char left in the buffer, since we 57 always (unless we get an error while reading the first char) 58 NUL-terminate the line buffer. */ 59 60 assert(*n - nchars_avail == read_pos - *lineptr); 61 if (nchars_avail < 2) { 62 if (*n > MIN_CHUNK) 63 *n *= 2; 64 else 65 *n += MIN_CHUNK; 66 67 nchars_avail = *n + *lineptr - read_pos; 68 *lineptr = realloc(*lineptr, *n); 69 if (!*lineptr) 70 return -1; 71 read_pos = *n - nchars_avail + *lineptr; 72 assert(*n - nchars_avail == read_pos - *lineptr); 73 } 74 75 if (c == EOF || ferror (stream)) { 76 /* Return partial line, if any. */ 77 if (read_pos == *lineptr) 78 return -1; 79 else 80 break; 81 } 82 83 *read_pos++ = c; 84 nchars_avail--; 85 86 if (c == terminator) 87 /* Return the line. */ 88 break; 89 } 90 91 /* Done - NUL terminate and return the number of chars read. */ 92 *read_pos = '\0'; 93 94 ret = read_pos - (*lineptr + offset); 95 return ret; 96 } 97 98 int getline (char **lineptr, size_t *n, FILE *stream) 99 { 100 return getstr(lineptr, n, stream, '\n', 0); 101 } 102