117721Speter/* getline.c -- Replacement for GNU C library function getline 217721Speter 317721SpeterCopyright (C) 1993 Free Software Foundation, Inc. 417721Speter 517721SpeterThis program is free software; you can redistribute it and/or 617721Spetermodify it under the terms of the GNU General Public License as 717721Speterpublished by the Free Software Foundation; either version 2 of the 817721SpeterLicense, or (at your option) any later version. 917721Speter 1017721SpeterThis program is distributed in the hope that it will be useful, but 1117721SpeterWITHOUT ANY WARRANTY; without even the implied warranty of 1217721SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1325839SpeterGeneral Public License for more details. */ 1417721Speter 1517721Speter/* Written by Jan Brittenson, bson@gnu.ai.mit.edu. */ 1617721Speter 1717721Speter#ifdef HAVE_CONFIG_H 1817721Speter#include <config.h> 1917721Speter#endif 2017721Speter 2117721Speter#include <sys/types.h> 2217721Speter#include <stdio.h> 2317721Speter#include <assert.h> 2432785Speter#include <errno.h> 2566525Speter#include "getline.h" 2617721Speter 2717721Speter#if STDC_HEADERS 2817721Speter#include <stdlib.h> 2917721Speter#else 3017721Speterchar *malloc (), *realloc (); 3117721Speter#endif 3217721Speter 3317721Speter/* Always add at least this many bytes when extending the buffer. */ 3417721Speter#define MIN_CHUNK 64 3517721Speter 3617721Speter/* Read up to (and including) a TERMINATOR from STREAM into *LINEPTR 3766525Speter + OFFSET (and null-terminate it). If LIMIT is non-negative, then 3866525Speter read no more than LIMIT chars. 3917721Speter 4066525Speter *LINEPTR is a pointer returned from malloc (or NULL), pointing to 4166525Speter *N characters of space. It is realloc'd as necessary. 4266525Speter 4366525Speter Return the number of characters read (not including the null 4466525Speter terminator), or -1 on error or EOF. On a -1 return, the caller 4566525Speter should check feof(), if not then errno has been set to indicate the 4666525Speter error. */ 4766525Speter 4817721Speterint 4966525Spetergetstr (lineptr, n, stream, terminator, offset, limit) 5017721Speter char **lineptr; 5117721Speter size_t *n; 5217721Speter FILE *stream; 53107484Speter int terminator; 5417721Speter int offset; 5566525Speter int limit; 5617721Speter{ 5717721Speter int nchars_avail; /* Allocated but unused chars in *LINEPTR. */ 5817721Speter char *read_pos; /* Where we're reading into *LINEPTR. */ 5917721Speter int ret; 6017721Speter 6117721Speter if (!lineptr || !n || !stream) 6232785Speter { 6332785Speter errno = EINVAL; 6432785Speter return -1; 6532785Speter } 6617721Speter 6717721Speter if (!*lineptr) 6817721Speter { 6917721Speter *n = MIN_CHUNK; 7017721Speter *lineptr = malloc (*n); 7117721Speter if (!*lineptr) 7232785Speter { 7332785Speter errno = ENOMEM; 7432785Speter return -1; 7532785Speter } 76102840Speter *lineptr[0] = '\0'; 7717721Speter } 7817721Speter 7917721Speter nchars_avail = *n - offset; 8017721Speter read_pos = *lineptr + offset; 8117721Speter 8217721Speter for (;;) 8317721Speter { 8432785Speter int save_errno; 8566525Speter register int c; 8617721Speter 8766525Speter if (limit == 0) 8866525Speter break; 8966525Speter else 9066525Speter { 9166525Speter c = getc (stream); 9266525Speter 9366525Speter /* If limit is negative, then we shouldn't pay attention to 9466525Speter it, so decrement only if positive. */ 9566525Speter if (limit > 0) 9666525Speter limit--; 9766525Speter } 9866525Speter 9932785Speter save_errno = errno; 10032785Speter 10117721Speter /* We always want at least one char left in the buffer, since we 10217721Speter always (unless we get an error while reading the first char) 10317721Speter NUL-terminate the line buffer. */ 10417721Speter 10517721Speter assert((*lineptr + *n) == (read_pos + nchars_avail)); 10617721Speter if (nchars_avail < 2) 10717721Speter { 10817721Speter if (*n > MIN_CHUNK) 10917721Speter *n *= 2; 11017721Speter else 11117721Speter *n += MIN_CHUNK; 11217721Speter 11317721Speter nchars_avail = *n + *lineptr - read_pos; 11417721Speter *lineptr = realloc (*lineptr, *n); 11517721Speter if (!*lineptr) 11632785Speter { 11732785Speter errno = ENOMEM; 11832785Speter return -1; 11932785Speter } 12017721Speter read_pos = *n - nchars_avail + *lineptr; 12117721Speter assert((*lineptr + *n) == (read_pos + nchars_avail)); 12217721Speter } 12317721Speter 12432785Speter if (ferror (stream)) 12517721Speter { 12632785Speter /* Might like to return partial line, but there is no 12732785Speter place for us to store errno. And we don't want to just 12832785Speter lose errno. */ 12932785Speter errno = save_errno; 13032785Speter return -1; 13132785Speter } 13232785Speter 13332785Speter if (c == EOF) 13432785Speter { 13517721Speter /* Return partial line, if any. */ 13617721Speter if (read_pos == *lineptr) 13717721Speter return -1; 13817721Speter else 13917721Speter break; 14017721Speter } 14117721Speter 14217721Speter *read_pos++ = c; 14317721Speter nchars_avail--; 14417721Speter 14517721Speter if (c == terminator) 14617721Speter /* Return the line. */ 14717721Speter break; 14817721Speter } 14917721Speter 15017721Speter /* Done - NUL terminate and return the number of chars read. */ 15117721Speter *read_pos = '\0'; 15217721Speter 15317721Speter ret = read_pos - (*lineptr + offset); 15417721Speter return ret; 15517721Speter} 15617721Speter 15717721Speterint 15817721Spetergetline (lineptr, n, stream) 15917721Speter char **lineptr; 16017721Speter size_t *n; 16117721Speter FILE *stream; 16217721Speter{ 16366525Speter return getstr (lineptr, n, stream, '\n', 0, GETLINE_NO_LIMIT); 16417721Speter} 16566525Speter 16666525Speterint 16766525Spetergetline_safe (lineptr, n, stream, limit) 16866525Speter char **lineptr; 16966525Speter size_t *n; 17066525Speter FILE *stream; 17166525Speter int limit; 17266525Speter{ 17366525Speter return getstr (lineptr, n, stream, '\n', 0, limit); 17466525Speter} 175