"Fossies" - the Fresh Open Source Software Archive

Member "gnuastro-0.9/bootstrapped/lib/getdelim.c" (17 Apr 2019, 3914 Bytes) of package /linux/privat/gnuastro-0.9.tar.lz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "getdelim.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.8_vs_0.9.

    1 /* getdelim.c --- Implementation of replacement getdelim function.
    2    Copyright (C) 1994, 1996-1998, 2001, 2003, 2005-2019 Free Software
    3    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 3, or (at
    8    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    You should have received a copy of the GNU General Public License
   16    along with this program; if not, see <https://www.gnu.org/licenses/>.  */
   17 
   18 /* Ported from glibc by Simon Josefsson. */
   19 
   20 /* Don't use __attribute__ __nonnull__ in this compilation unit.  Otherwise gcc
   21    optimizes away the lineptr == NULL || n == NULL || fp == NULL tests below.  */
   22 #define _GL_ARG_NONNULL(params)
   23 
   24 #include <config.h>
   25 
   26 #include <stdio.h>
   27 
   28 #include <limits.h>
   29 #include <stdint.h>
   30 #include <stdlib.h>
   31 #include <errno.h>
   32 
   33 #ifndef SSIZE_MAX
   34 # define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
   35 #endif
   36 
   37 #if USE_UNLOCKED_IO
   38 # include "unlocked-io.h"
   39 # define getc_maybe_unlocked(fp)        getc(fp)
   40 #elif !HAVE_FLOCKFILE || !HAVE_FUNLOCKFILE || !HAVE_DECL_GETC_UNLOCKED
   41 # undef flockfile
   42 # undef funlockfile
   43 # define flockfile(x) ((void) 0)
   44 # define funlockfile(x) ((void) 0)
   45 # define getc_maybe_unlocked(fp)        getc(fp)
   46 #else
   47 # define getc_maybe_unlocked(fp)        getc_unlocked(fp)
   48 #endif
   49 
   50 static void
   51 alloc_failed (void)
   52 {
   53 #if defined _WIN32 && ! defined __CYGWIN__
   54   /* Avoid errno problem without using the realloc module; see:
   55      https://lists.gnu.org/r/bug-gnulib/2016-08/msg00025.html  */
   56   errno = ENOMEM;
   57 #endif
   58 }
   59 
   60 /* Read up to (and including) a DELIMITER from FP into *LINEPTR (and
   61    NUL-terminate it).  *LINEPTR is a pointer returned from malloc (or
   62    NULL), pointing to *N characters of space.  It is realloc'ed as
   63    necessary.  Returns the number of characters read (not including
   64    the null terminator), or -1 on error or EOF.  */
   65 
   66 ssize_t
   67 getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp)
   68 {
   69   ssize_t result;
   70   size_t cur_len = 0;
   71 
   72   if (lineptr == NULL || n == NULL || fp == NULL)
   73     {
   74       errno = EINVAL;
   75       return -1;
   76     }
   77 
   78   flockfile (fp);
   79 
   80   if (*lineptr == NULL || *n == 0)
   81     {
   82       char *new_lineptr;
   83       *n = 120;
   84       new_lineptr = (char *) realloc (*lineptr, *n);
   85       if (new_lineptr == NULL)
   86         {
   87           alloc_failed ();
   88           result = -1;
   89           goto unlock_return;
   90         }
   91       *lineptr = new_lineptr;
   92     }
   93 
   94   for (;;)
   95     {
   96       int i;
   97 
   98       i = getc_maybe_unlocked (fp);
   99       if (i == EOF)
  100         {
  101           result = -1;
  102           break;
  103         }
  104 
  105       /* Make enough space for len+1 (for final NUL) bytes.  */
  106       if (cur_len + 1 >= *n)
  107         {
  108           size_t needed_max =
  109             SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX;
  110           size_t needed = 2 * *n + 1;   /* Be generous. */
  111           char *new_lineptr;
  112 
  113           if (needed_max < needed)
  114             needed = needed_max;
  115           if (cur_len + 1 >= needed)
  116             {
  117               result = -1;
  118               errno = EOVERFLOW;
  119               goto unlock_return;
  120             }
  121 
  122           new_lineptr = (char *) realloc (*lineptr, needed);
  123           if (new_lineptr == NULL)
  124             {
  125               alloc_failed ();
  126               result = -1;
  127               goto unlock_return;
  128             }
  129 
  130           *lineptr = new_lineptr;
  131           *n = needed;
  132         }
  133 
  134       (*lineptr)[cur_len] = i;
  135       cur_len++;
  136 
  137       if (i == delimiter)
  138         break;
  139     }
  140   (*lineptr)[cur_len] = '\0';
  141   result = cur_len ? cur_len : result;
  142 
  143  unlock_return:
  144   funlockfile (fp); /* doesn't set errno */
  145 
  146   return result;
  147 }