PageRenderTime 48ms CodeModel.GetById 36ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/cvs/lib/getline.c

https://bitbucket.org/freebsd/freebsd-head/
C | 174 lines | 112 code | 25 blank | 37 comment | 21 complexity | 8cdfb1910fe6f3ab4df66f52d6b7a692 MD5 | raw file
  1/* getline.c -- Replacement for GNU C library function getline
  2
  3Copyright (C) 1993 Free Software Foundation, Inc.
  4
  5This program is free software; you can redistribute it and/or
  6modify it under the terms of the GNU General Public License as
  7published by the Free Software Foundation; either version 2 of the
  8License, or (at your option) any later version.
  9
 10This program is distributed in the hope that it will be useful, but
 11WITHOUT ANY WARRANTY; without even the implied warranty of
 12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13General 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#include <errno.h>
 25#include "getline.h"
 26
 27#if STDC_HEADERS
 28#include <stdlib.h>
 29#else
 30char *malloc (), *realloc ();
 31#endif
 32
 33/* Always add at least this many bytes when extending the buffer.  */
 34#define MIN_CHUNK 64
 35
 36/* Read up to (and including) a TERMINATOR from STREAM into *LINEPTR
 37   + OFFSET (and null-terminate it).  If LIMIT is non-negative, then
 38   read no more than LIMIT chars.
 39
 40   *LINEPTR is a pointer returned from malloc (or NULL), pointing to
 41   *N characters of space.  It is realloc'd as necessary.  
 42
 43   Return the number of characters read (not including the null
 44   terminator), or -1 on error or EOF.  On a -1 return, the caller
 45   should check feof(), if not then errno has been set to indicate the
 46   error.  */
 47
 48int
 49getstr (lineptr, n, stream, terminator, offset, limit)
 50     char **lineptr;
 51     size_t *n;
 52     FILE *stream;
 53     int terminator;
 54     int offset;
 55     int limit;
 56{
 57  int nchars_avail;		/* Allocated but unused chars in *LINEPTR.  */
 58  char *read_pos;		/* Where we're reading into *LINEPTR. */
 59  int ret;
 60
 61  if (!lineptr || !n || !stream)
 62    {
 63      errno = EINVAL;
 64      return -1;
 65    }
 66
 67  if (!*lineptr)
 68    {
 69      *n = MIN_CHUNK;
 70      *lineptr = malloc (*n);
 71      if (!*lineptr)
 72	{
 73	  errno = ENOMEM;
 74	  return -1;
 75	}
 76      *lineptr[0] = '\0';
 77    }
 78
 79  nchars_avail = *n - offset;
 80  read_pos = *lineptr + offset;
 81
 82  for (;;)
 83    {
 84      int save_errno;
 85      register int c;
 86
 87      if (limit == 0)
 88          break;
 89      else
 90      {
 91          c = getc (stream);
 92
 93          /* If limit is negative, then we shouldn't pay attention to
 94             it, so decrement only if positive. */
 95          if (limit > 0)
 96              limit--;
 97      }
 98
 99      save_errno = errno;
100
101      /* We always want at least one char left in the buffer, since we
102	 always (unless we get an error while reading the first char)
103	 NUL-terminate the line buffer.  */
104
105      assert((*lineptr + *n) == (read_pos + nchars_avail));
106      if (nchars_avail < 2)
107	{
108	  if (*n > MIN_CHUNK)
109	    *n *= 2;
110	  else
111	    *n += MIN_CHUNK;
112
113	  nchars_avail = *n + *lineptr - read_pos;
114	  *lineptr = realloc (*lineptr, *n);
115	  if (!*lineptr)
116	    {
117	      errno = ENOMEM;
118	      return -1;
119	    }
120	  read_pos = *n - nchars_avail + *lineptr;
121	  assert((*lineptr + *n) == (read_pos + nchars_avail));
122	}
123
124      if (ferror (stream))
125	{
126	  /* Might like to return partial line, but there is no
127	     place for us to store errno.  And we don't want to just
128	     lose errno.  */
129	  errno = save_errno;
130	  return -1;
131	}
132
133      if (c == EOF)
134	{
135	  /* Return partial line, if any.  */
136	  if (read_pos == *lineptr)
137	    return -1;
138	  else
139	    break;
140	}
141
142      *read_pos++ = c;
143      nchars_avail--;
144
145      if (c == terminator)
146	/* Return the line.  */
147	break;
148    }
149
150  /* Done - NUL terminate and return the number of chars read.  */
151  *read_pos = '\0';
152
153  ret = read_pos - (*lineptr + offset);
154  return ret;
155}
156
157int
158getline (lineptr, n, stream)
159     char **lineptr;
160     size_t *n;
161     FILE *stream;
162{
163  return getstr (lineptr, n, stream, '\n', 0, GETLINE_NO_LIMIT);
164}
165
166int
167getline_safe (lineptr, n, stream, limit)
168     char **lineptr;
169     size_t *n;
170     FILE *stream;
171     int limit;
172{
173  return getstr (lineptr, n, stream, '\n', 0, limit);
174}