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