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