bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Bug-gnulib] getline & getline_safe


From: Derek Robert Price
Subject: Re: [Bug-gnulib] getline & getline_safe
Date: Fri, 18 Jul 2003 16:33:42 -0400
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030624 Netscape/7.1

Bruno Haible wrote:

Derek Robert Price wrote:
+ssize_t
+getndelim2 (char **lineptr, size_t *linesize, size_t offset, int limit,
+            int delim1, int delim2, FILE *stream)

What's the purpose of having the offset as 3rd argument when historically
(and in the coreutils) it comes last?


When I wrote that, I didn't realize coreutils was using getndelim2 and figured that since I was exposing a new API, I might as well rearrange it to group the items that had to do with buffers and counts and keep the FILE * last, as getdelim() does when it inserts the delimiter before the FILE * argument as compared to getline(). This keeps the APIs of all 5 functions looking consistent.

If coreutils is currently the only one using the function, it would make sense to reorganize the API now, before it makes it into more common usage.

+# define GETNDELIM_NO_LIMIT (ssize_t)-1

Totally confusing types: the limit is an upper bound for the size of an
array or count, so it should be 'size_t'. The getndelim2() argument called
limit is of type 'int'. And this macro is of type 'ssize_t'. Better let
the caller use 'size_t' everywhere.


No I'm not. Or at least I may not have been consistent about updating my types, but it should be ssize_t everywhere, if the return type is to be ssize_t. Don't forget that I wrote this to use limit as a maximum number of characters. If the number of characters read is returned as an ssize_t then the number of characters to read should be passed in as an ssize_t as well.

--- modules/getnline    17 Jul 2003 16:23:52 -0000      1.1
+++ modules/getnline    17 Jul 2003 19:09:58 -0000
@@ -1,10 +1,12 @@
Description:
-Read a line from a stream, with bounded memory allocation.
+Read a line of n characters or less from a stream.

Files:
+lib/getndelim2.h
+lib/getndelim2.c
lib/getnline.h
lib/getnline.c
-lib/getndelim2.c
+m4/getndelim2.m4
m4/getnline.m4
m4/ssize_t.m4

@@ -15,8 +17,7 @@
gl_GETNLINE

Makefile.am:
-lib_SOURCES += getnline.h
-EXTRA_DIST += getndelim2.c
+lib_SOURCES += getnline.h getndelim2.h

Include:
"getnline.h"

It's simpler to make the module 'getnline' depend on the module 'getndelim2'.

Whoops. This is correct. I've merged your recent changes back into my patch so it is considerably smaller. Please comment.

        * lib/getline.c: Don't include files included in lib/getline.h.
        (getline, getdelim): Return ssize_t.  Use new getndelim2 API.
        * lib/getline.h: Include config.h when possible.  Include sys/types.h
        for ssize_t.  Prototype functions to return ssize_t rather than int.
        Switch getline & getdelim protos on what configure actually detected
        rather than the value of __GLIBC__.
* lib/getndelim2.c: Match description to new API. (getndelim2): Reorder API to match the other get*line & get*delim
        functions.  Rewrite most of Bruno's nmax changes to set a maximum
        number of characters read rather than a maximum number of bytes to
        allocate.
        * lib/getndelim2.h: Match description to new API.  Match proto to new
        API.
        * lib/getnline.c: Match description to new API.
        (getnline, getndelim): Use new getndelim2 API.
        * lib/getnline.h: Match descriptions and protos to new API.
        * m4/getline.m4: Increment serial.  Define HAVE_WORKING_GETLINE &
        HAVE_GETDELIM for getline.h.
        * modules/getnline: Change description to match functions.
        * modules/getndelim2: Ditto.


Index: lib/getline.c
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/getline.c,v
retrieving revision 1.14
diff -u -r1.14 getline.c
--- lib/getline.c       18 Jul 2003 16:58:06 -0000      1.14
+++ lib/getline.c       18 Jul 2003 20:27:56 -0000
@@ -32,12 +32,9 @@
# define _GNU_SOURCE 1
#endif

-#include <stddef.h>
-#include <stdio.h>
-
#if defined __GNU_LIBRARY__ && HAVE_GETDELIM

-int
+ssize_t
getline (char **lineptr, size_t *linesize, FILE *stream)
{
  return getdelim (lineptr, linesize, '\n', stream);
@@ -47,15 +44,17 @@

#include "getndelim2.h"

-int
+ssize_t
getline (char **lineptr, size_t *linesize, FILE *stream)
{
-  return getndelim2 (lineptr, linesize, (size_t)(-1), stream, '\n', 0, 0);
+  return getndelim2 (lineptr, linesize, 0, GETNDELIM_NO_LIMIT, '\n', 0,
+                     stream);
}

-int
+ssize_t
getdelim (char **lineptr, size_t *linesize, int delimiter, FILE *stream)
{
-  return getndelim2 (lineptr, linesize, (size_t)(-1), stream, delimiter, 0, 0);
+  return getndelim2 (lineptr, linesize, 0, GETNDELIM_NO_LIMIT, delimiter, 0,
+                     stream);
}
-#endif
+#endif /* have getdelim */
Index: lib/getline.h
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/getline.h,v
retrieving revision 1.13
diff -u -r1.13 getline.h
--- lib/getline.h       18 Jul 2003 16:58:06 -0000      1.13
+++ lib/getline.h       18 Jul 2003 20:27:56 -0000
@@ -20,17 +20,28 @@
#ifndef GETLINE_H_
# define GETLINE_H_ 1

+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
# include <stddef.h>
# include <stdio.h>

+/* Get ssize_t.  */
+#include <sys/types.h>
+
/* glibc2 has these functions declared in <stdio.h>.  Avoid redeclarations.  */
-# if __GLIBC__ < 2
+# if !HAVE_WORKING_GETLINE
+
+extern ssize_t getline (char **_lineptr, size_t *_linesize, FILE *_stream);
+
+# endif /* ! have getline */

-extern int getline (char **_lineptr, size_t *_linesize, FILE *_stream);
+# if !HAVE_GETDELIM

-extern int getdelim (char **_lineptr, size_t *_linesize, int _delimiter,
-                    FILE *_stream);
+extern ssize_t getdelim (char **_lineptr, size_t *_linesize, int _delimiter,
+                         FILE *_stream);

-# endif
+# endif /* ! have getdelim */

#endif /* not GETLINE_H_ */
Index: lib/getndelim2.c
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/getndelim2.c,v
retrieving revision 1.2
diff -u -r1.2 getndelim2.c
--- lib/getndelim2.c    18 Jul 2003 16:58:06 -0000      1.2
+++ lib/getndelim2.c    18 Jul 2003 20:27:56 -0000
@@ -1,5 +1,5 @@
-/* getndelim2 - Read a line from a stream, stopping at one of 2 delimiters,
-   with bounded memory allocation.
+/* getndelim2 - Read n characters or less from a stream, stopping at one of up
+   to two specified delimiters.

   Copyright (C) 1993, 1996, 1997, 1998, 2000, 2003 Free Software
   Foundation, Inc.
@@ -39,23 +39,18 @@
#define MIN_CHUNK 64

ssize_t
-getndelim2 (char **lineptr, size_t *linesize, size_t nmax,
-           FILE *stream, int delim1, int delim2, size_t offset)
+getndelim2 (char **lineptr, size_t *linesize, size_t offset, ssize_t limit,
+            int delim1, int delim2, FILE *stream)
{
  size_t nbytes_avail;          /* Allocated but unused chars in *LINEPTR.  */
  char *read_pos;               /* Where we're reading into *LINEPTR. */

-  if (!lineptr || !linesize || !nmax || !stream)
+  if (!lineptr || !linesize || !stream)
    return -1;

  if (!*lineptr)
    {
-      size_t newlinesize = MIN_CHUNK;
-
-      if (newlinesize > nmax)
-       newlinesize = nmax;
-
-      *linesize = newlinesize;
+      *linesize = MIN_CHUNK;
      *lineptr = malloc (*linesize);
      if (!*lineptr)
        return -1;
@@ -67,36 +62,35 @@
  nbytes_avail = *linesize - offset;
  read_pos = *lineptr + offset;

-  if (nbytes_avail == 0 && *linesize >= nmax)
-    return -1;
-
  for (;;)
    {
      /* Here always *lineptr + *linesize == read_pos + nbytes_avail.  */
+      register int c;
+
+      if (limit == 0)
+       break;
+
+      c = getc (stream);

-      register int c = getc (stream);
+      if (limit != GETNDELIM_NO_LIMIT)
+       limit--;

      /* We always want at least one char left in the buffer, since we
         always (unless we get an error while reading the first char)
         NUL-terminate the line buffer.  */

-      if (nbytes_avail < 2 && *linesize < nmax)
+      if (nbytes_avail < 2)
        {
-         size_t newlinesize =
-           (*linesize > MIN_CHUNK ? 2 * *linesize : *linesize + MIN_CHUNK);
-
-         if (newlinesize > nmax)
-           newlinesize = nmax;
+         if (*linesize > MIN_CHUNK)
+           *linesize *= 2;
+         else
+           *linesize += MIN_CHUNK;

-         if (newlinesize > *linesize)
-           {
-             *linesize = newlinesize;
-             nbytes_avail = *linesize + *lineptr - read_pos;
-             *lineptr = realloc (*lineptr, *linesize);
-             if (!*lineptr)
-               return -1;
-             read_pos = *linesize - nbytes_avail + *lineptr;
-           }
+         nbytes_avail = *linesize + *lineptr - read_pos;
+         *lineptr = realloc (*lineptr, *linesize);
+         if (!*lineptr)
+           return -1;
+         read_pos = *linesize - nbytes_avail + *lineptr;
        }

      if (c == EOF || ferror (stream))
@@ -108,11 +102,8 @@
            break;
        }

-      if (nbytes_avail >= 2)
-       {
-         *read_pos++ = c;
-         nbytes_avail--;
-       }
+      *read_pos++ = c;
+      nbytes_avail--;

      if (c == delim1 || (delim2 && c == delim2))
        /* Return the line.  */
Index: lib/getndelim2.h
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/getndelim2.h,v
retrieving revision 1.1
diff -u -r1.1 getndelim2.h
--- lib/getndelim2.h    18 Jul 2003 16:58:06 -0000      1.1
+++ lib/getndelim2.h    18 Jul 2003 20:27:56 -0000
@@ -1,5 +1,5 @@
-/* getndelim2 - Read a line from a stream, stopping at one of 2 delimiters,
-   with bounded memory allocation.
+/* getndelim2 - Read n characters or less from a stream, stopping at one of up
+   to two specified delimiters.

   Copyright (C) 2003 Free Software Foundation, Inc.

@@ -26,17 +26,17 @@
/* Get ssize_t.  */
#include <sys/types.h>

+#define GETNDELIM_NO_LIMIT (ssize_t)-1
+
/* Read up to (and including) a delimiter DELIM1 from STREAM into *LINEPTR
   + OFFSET (and NUL-terminate it).  If DELIM2 is non-zero, then read up
   and including the first occurrence of DELIM1 or DELIM2.  *LINEPTR is
   a pointer returned from malloc (or NULL), pointing to *LINESIZE bytes of
-   space.  It is realloc'd as necessary.  Reallocation is limited to
-   NMAX bytes; if the line is longer than that, the extra bytes are read but
-   thrown away.
+   space.  It is realloc'd as necessary.  Read no more than LIMIT bytes.
   Return the number of bytes read and stored at *LINEPTR + OFFSET (not
   including the NUL terminator), or -1 on error or EOF.  */
-extern ssize_t getndelim2 (char **lineptr, size_t *linesize, size_t nmax,
-                          FILE *stream, int delim1, int delim2,
-                          size_t offset);
+extern ssize_t getndelim2 (char **_lineptr, size_t *_linesize, size_t _offset,
+                           ssize_t _limit, int _delim1, int _delim2,
+                           FILE *_stream);

#endif /* GETNDELIM2_H */
Index: lib/getnline.c
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/getnline.c,v
retrieving revision 1.2
diff -u -r1.2 getnline.c
--- lib/getnline.c      18 Jul 2003 16:58:06 -0000      1.2
+++ lib/getnline.c      18 Jul 2003 20:27:56 -0000
@@ -1,4 +1,4 @@
-/* getnline - Read a line from a stream, with bounded memory allocation.
+/* getnline - Read a line of n characters or less from a stream.

   Copyright (C) 2003 Free Software Foundation, Inc.

@@ -26,14 +26,14 @@
#include "getndelim2.h"

ssize_t
-getnline (char **lineptr, size_t *linesize, size_t nmax, FILE *stream)
+getnline (char **lineptr, size_t *linesize, ssize_t limit, FILE *stream)
{
-  return getndelim2 (lineptr, linesize, (size_t)(-1), stream, '\n', 0, 0);
+  return getndelim2 (lineptr, linesize, 0, limit, '\n', 0, stream);
}

ssize_t
-getndelim (char **lineptr, size_t *linesize, size_t nmax,
-          int delimiter, FILE *stream)
+getndelim (char **lineptr, size_t *linesize, ssize_t limit, int delimiter,
+           FILE *stream)
{
-  return getndelim2 (lineptr, linesize, (size_t)(-1), stream, delimiter, 0, 0);
+  return getndelim2 (lineptr, linesize, 0, limit, delimiter, 0, stream);
}
Index: lib/getnline.h
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/getnline.h,v
retrieving revision 1.1
diff -u -r1.1 getnline.h
--- lib/getnline.h      17 Jul 2003 16:23:52 -0000      1.1
+++ lib/getnline.h      18 Jul 2003 20:27:56 -0000
@@ -1,4 +1,4 @@
-/* getnline - Read a line from a stream, with bounded memory allocation.
+/* getnline - Read a line of n characters or less from a stream.

   Copyright (C) 2003 Free Software Foundation, Inc.

@@ -27,23 +27,21 @@

/* Read a line, up to the next newline, from STREAM, and store it in *LINEPTR.
   *LINEPTR is a pointer returned from malloc (or NULL), pointing to *LINESIZE
-   bytes of space.  It is realloc'd as necessary.  Reallocation is limited to
-   NMAX bytes; if the line is longer than that, the extra bytes are read but
-   thrown away.
+   bytes of space.  It is realloc'd as necessary.  Read a maximum of LIMIT
+   bytes.
   Return the number of bytes read and stored at *LINEPTR (not including the
   NUL terminator), or -1 on error or EOF.  */
-extern ssize_t getnline (char **lineptr, size_t *linesize, size_t nmax,
-                        FILE *stream);
+extern ssize_t getnline (char **_lineptr, size_t *_linesize, ssize_t limit,
+                         FILE *_stream);

/* Read a line, up to the next occurrence of DELIMITER, from STREAM, and store
   it in *LINEPTR.
   *LINEPTR is a pointer returned from malloc (or NULL), pointing to *LINESIZE
-   bytes of space.  It is realloc'd as necessary.  Reallocation is limited to
-   NMAX bytes; if the line is longer than that, the extra bytes are read but
-   thrown away.
+   bytes of space.  It is realloc'd as necessary.  Read a maximum of LIMIT
+   bytes.
   Return the number of bytes read and stored at *LINEPTR (not including the
   NUL terminator), or -1 on error or EOF.  */
-extern ssize_t getndelim (char **lineptr, size_t *linesize, size_t nmax,
-                         int delimiter, FILE *stream);
+extern ssize_t getndelim (char **_lineptr, size_t *_linesize, ssize_t limit,
+                          int _delimiter, FILE *_stream);

#endif /* GETNLINE_H */
Index: m4/getline.m4
===================================================================
RCS file: /cvsroot/gnulib/gnulib/m4/getline.m4,v
retrieving revision 1.12
diff -u -r1.12 getline.m4
--- m4/getline.m4       18 Jul 2003 16:58:06 -0000      1.12
+++ m4/getline.m4       18 Jul 2003 20:27:56 -0000
@@ -1,4 +1,4 @@
-# getline.m4 serial 9
+# getline.m4 serial 10

dnl Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software
dnl Foundation, Inc.
@@ -49,7 +49,15 @@
    )])
  fi

-  if test $am_cv_func_working_getline = no; then
+  if test $am_cv_func_working_getline = yes; then
+    AC_DEFINE([HAVE_WORKING_GETLINE], [1],
+      [Define to 1 if your system has a working GNU getline() function.])
+    dnl Currently, we assume getdelim() in this case.  Moving the check for
+    dnl getdelim() up in front of this conditional doesn't make much sense
+    dnl unless we provide for having getline w/o getdelim in the *.{c,h} files.
+    AC_DEFINE([HAVE_GETDELIM], [1],
+      [Define to 1 if your system has the GNU getdelim() function.])
+  else
    dnl We must choose a different name for our function, since on ELF systems
    dnl a broken getline() in libc.so would override our getline() in
    dnl libgettextlib.so.
Index: modules/getndelim2
===================================================================
RCS file: /cvsroot/gnulib/gnulib/modules/getndelim2,v
retrieving revision 1.1
diff -u -r1.1 getndelim2
--- modules/getndelim2  18 Jul 2003 16:58:06 -0000      1.1
+++ modules/getndelim2  18 Jul 2003 20:27:56 -0000
@@ -1,6 +1,6 @@
Description:
-Read a line from a stream, stopping at one of 2 delimiters, with bounded
-memory allocation.
+Read n characters or less from a stream, stopping at one of up to two specified
+delimiters.

Files:
lib/getndelim2.h
Index: modules/getnline
===================================================================
RCS file: /cvsroot/gnulib/gnulib/modules/getnline,v
retrieving revision 1.2
diff -u -r1.2 getnline
--- modules/getnline    18 Jul 2003 16:58:06 -0000      1.2
+++ modules/getnline    18 Jul 2003 20:27:56 -0000
@@ -1,5 +1,5 @@
Description:
-Read a line from a stream, with bounded memory allocation.
+Read a line of n characters or less from a stream.

Files:
lib/getnline.h



Derek

--
               *8^)

Email: address@hidden

Get CVS support at <http://ximbiot.com>!
--
Duct tape is like the Force.  It has a light side, a dark side, and it
holds the Universe together.






reply via email to

[Prev in Thread] Current Thread [Next in Thread]