Back to index

glibc  2.9
iogetdelim.c
Go to the documentation of this file.
00001 /* Copyright (C) 1994,1996-1998,2001,2003,2005 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Lesser General Public
00006    License as published by the Free Software Foundation; either
00007    version 2.1 of the License, or (at your option) any later version.
00008 
00009    The GNU C Library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Lesser General Public License for more details.
00013 
00014    You should have received a copy of the GNU Lesser General Public
00015    License along with the GNU C Library; if not, write to the Free
00016    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00017    02111-1307 USA.
00018 
00019    As a special exception, if you link the code in this file with
00020    files compiled with a GNU compiler to produce an executable,
00021    that does not cause the resulting executable to be covered by
00022    the GNU Lesser General Public License.  This exception does not
00023    however invalidate any other reasons why the executable file
00024    might be covered by the GNU Lesser General Public License.
00025    This exception applies to code released by its copyright holders
00026    in files containing the exception.  */
00027 
00028 #ifdef __STDC__
00029 #include <stdlib.h>
00030 #endif
00031 #include "libioP.h"
00032 #include <string.h>
00033 #include <errno.h>
00034 
00035 /* Read up to (and including) a TERMINATOR from FP into *LINEPTR
00036    (and null-terminate it).  *LINEPTR is a pointer returned from malloc (or
00037    NULL), pointing to *N characters of space.  It is realloc'ed as
00038    necessary.  Returns the number of characters read (not including the
00039    null terminator), or -1 on error or EOF.  */
00040 
00041 _IO_ssize_t
00042 _IO_getdelim (lineptr, n, delimiter, fp)
00043      char **lineptr;
00044      _IO_size_t *n;
00045      int delimiter;
00046      _IO_FILE *fp;
00047 {
00048   _IO_ssize_t result;
00049   _IO_ssize_t cur_len = 0;
00050   _IO_ssize_t len;
00051 
00052   if (lineptr == NULL || n == NULL)
00053     {
00054       MAYBE_SET_EINVAL;
00055       return -1;
00056     }
00057   CHECK_FILE (fp, -1);
00058   _IO_acquire_lock (fp);
00059   if (_IO_ferror_unlocked (fp))
00060     {
00061       result = -1;
00062       goto unlock_return;
00063     }
00064 
00065   if (*lineptr == NULL || *n == 0)
00066     {
00067       *n = 120;
00068       *lineptr = (char *) malloc (*n);
00069       if (*lineptr == NULL)
00070        {
00071          result = -1;
00072          goto unlock_return;
00073        }
00074     }
00075 
00076   len = fp->_IO_read_end - fp->_IO_read_ptr;
00077   if (len <= 0)
00078     {
00079       if (__underflow (fp) == EOF)
00080        {
00081          result = -1;
00082          goto unlock_return;
00083        }
00084       len = fp->_IO_read_end - fp->_IO_read_ptr;
00085     }
00086 
00087   for (;;)
00088     {
00089       _IO_size_t needed;
00090       char *t;
00091       t = (char *) memchr ((void *) fp->_IO_read_ptr, delimiter, len);
00092       if (t != NULL)
00093        len = (t - fp->_IO_read_ptr) + 1;
00094       if (__builtin_expect (cur_len + len + 1 < 0, 0))
00095        {
00096          __set_errno (EOVERFLOW);
00097          result = -1;
00098          goto unlock_return;
00099        }
00100       /* Make enough space for len+1 (for final NUL) bytes.  */
00101       needed = cur_len + len + 1;
00102       if (needed > *n)
00103        {
00104          char *new_lineptr;
00105 
00106          if (needed < 2 * *n)
00107            needed = 2 * *n;  /* Be generous. */
00108          new_lineptr = (char *) realloc (*lineptr, needed);
00109          if (new_lineptr == NULL)
00110            {
00111              result = -1;
00112              goto unlock_return;
00113            }
00114          *lineptr = new_lineptr;
00115          *n = needed;
00116        }
00117       memcpy (*lineptr + cur_len, (void *) fp->_IO_read_ptr, len);
00118       fp->_IO_read_ptr += len;
00119       cur_len += len;
00120       if (t != NULL || __underflow (fp) == EOF)
00121        break;
00122       len = fp->_IO_read_end - fp->_IO_read_ptr;
00123     }
00124   (*lineptr)[cur_len] = '\0';
00125   result = cur_len;
00126 
00127 unlock_return:
00128   _IO_release_lock (fp);
00129   return result;
00130 }
00131 
00132 #ifdef weak_alias
00133 weak_alias (_IO_getdelim, __getdelim)
00134 weak_alias (_IO_getdelim, getdelim)
00135 #endif