bug-cvs
[Top][All Lists]
Advanced

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

01-getnline.diff (was Re: [Bug-gnulib] getline & getline_safe)


From: Derek Robert Price
Subject: 01-getnline.diff (was Re: [Bug-gnulib] getline & getline_safe)
Date: Wed, 16 Jul 2003 15:56:33 -0400
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030624 Netscape/7.1

Paul Eggert wrote:

Derek Robert Price <derek@ximbiot.com> writes:
Incidentally, this implies having a getnline.c file which is always
compiled, and possibly which getline.c is dependent on.  Is this
reasonable?
Sounds reasonable to me.
The long run alternative is to get getndelim() & getnline() into
libc.  I haven't really dealt with libc before.  Is _this_
reasonable?  Is this likely?
Maybe, maybe not.  Let's try gnulib first.  If only CVS uses it, then
perhaps it's not worth worrying about for libc.

Okay, here's my first pass. It configures, builds, and passes `make check' with CVS, so I updated modules/getline, created modules/getnline, and am resubmitting to bug-gnulib. Please let me know what you think.

I call it a first pass only because I wasn't sure how to document this complex dependency. I think what I did was acceptable, but notice that I duplicated the getnline.* stuff between the two module descriptions. The basic difference is that if you want getline compiled conditionally but getnline compiled unconditionally then you add a call to gl_PREREQ_GETNLINE to configure.ac. This is what I did with CVS. If you just include the info as per the modules/getline file, getnline.c will only be compiled when it is needed for getline.c.

I still need to write the ChangeLog for CVS but I should commit these changes there soon.

Incidentally, my glibc defines both getdelim & getline to return ssize_t. Is it intentional that the GNULIB versions return int instead?

        * lib/getnline.c: New file.
        * lib/getnline.h: Ditto.
        * m4/getnline.m4: Ditto.
        * modules/getnline: Ditto.

        * lib/getline.c: Move some include cruft with getdelim2 below.
        (getdelim2): Move to the new getnline.c above.
        (getdelim, getline): Wrap getndelim & getnline, respectitvely.
        * lib/getline.h: Use HAVE_WORKING_GETLINE & HAVE_GETDELIM rather than
        __GLIBC__ < 2, as per the autoconf paradigm.
        * m4/getline.m4 (AM_FUNC_GETLINE): Define HAVE_WORKING_GETLINE when
        appropriate.
        (gl_PREREQ_GETLINE): Call gl_PREREQ_GETNLINE when getdelim is not
        found.
        * modules/getline: Add new files to module setup instructions.


Index: lib/getline.c
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/getline.c,v
retrieving revision 1.12
diff -u -r1.12 getline.c
--- lib/getline.c       4 Jun 2003 19:22:29 -0000       1.12
+++ lib/getline.c       16 Jul 2003 19:50:47 -0000
@@ -17,7 +17,9 @@
   along with this program; if not, write to the Free Software Foundation,
   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */

-/* Written by Jan Brittenson, bson@gnu.ai.mit.edu.  */
+/* Adapted by Derek Price <derek@ximbiot.com>
+ * from getline.c written by Jan Brittenson <bson@gnu.ai.mit.edu>.
+ */

#if HAVE_CONFIG_H
# include <config.h>
@@ -44,105 +46,18 @@

#else /* ! have getdelim */

-# if STDC_HEADERS
-#  include <stdlib.h>
-# else
-char *malloc (), *realloc ();
-# endif
-
-#include "unlocked-io.h"
-
-/* Always add at least this many bytes when extending the buffer.  */
-#define MIN_CHUNK 64
-
-/* 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 *N characters of
-   space.  It is realloc'd as necessary.  Return the number of characters
-   read (not including the NUL terminator), or -1 on error or EOF.  */
-
-static int
-getdelim2 (char **lineptr, size_t *n, FILE *stream, int delim1, int delim2,
-          size_t offset)
-{
-  size_t nchars_avail;         /* Allocated but unused chars in *LINEPTR.  */
-  char *read_pos;              /* Where we're reading into *LINEPTR. */
-  int ret;
-
-  if (!lineptr || !n || !stream)
-    return -1;
-
-  if (!*lineptr)
-    {
-      *n = MIN_CHUNK;
-      *lineptr = malloc (*n);
-      if (!*lineptr)
-       return -1;
-    }
-
-  if (*n < offset)
-    return -1;
-
-  nchars_avail = *n - offset;
-  read_pos = *lineptr + offset;
-
-  for (;;)
-    {
-      register int c = getc (stream);
-
-      /* 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 (nchars_avail < 2)
-       {
-         if (*n > MIN_CHUNK)
-           *n *= 2;
-         else
-           *n += MIN_CHUNK;
-
-         nchars_avail = *n + *lineptr - read_pos;
-         *lineptr = realloc (*lineptr, *n);
-         if (!*lineptr)
-           return -1;
-         read_pos = *n - nchars_avail + *lineptr;
-       }
-
-      if (c == EOF || ferror (stream))
-       {
-         /* Return partial line, if any.  */
-         if (read_pos == *lineptr)
-           return -1;
-         else
-           break;
-       }
-
-      *read_pos++ = c;
-      nchars_avail--;
-
-      if (c == delim1 || (delim2 && c == delim2))
-       /* Return the line.  */
-       break;
-    }
-
-  /* Done - NUL terminate and return the number of chars read.  */
-  *read_pos = '\0';
-
-  ret = read_pos - (*lineptr + offset);
-  return ret;
-}
-
+# include "getnline.h"
+# include "unlocked-io.h"

int
getline (char **lineptr, size_t *n, FILE *stream)
{
-  return getdelim2 (lineptr, n, stream, '\n', 0, 0);
+  return getnline (lineptr, n, stream, GETNDELIM_NO_LIMIT);
}

int
getdelim (char **lineptr, size_t *n, int delimiter, FILE *stream)
{
-  return getdelim2 (lineptr, n, stream, delimiter, 0, 0);
+  return getndelim (lineptr, n, delimiter, stream, GETNDELIM_NO_LIMIT);
}
-#endif
+#endif /* have getdelim */
Index: lib/getline.h
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/getline.h,v
retrieving revision 1.12
diff -u -r1.12 getline.h
--- lib/getline.h       18 Jun 2003 05:52:19 -0000      1.12
+++ lib/getline.h       16 Jul 2003 19:50:47 -0000
@@ -24,12 +24,16 @@
# include <stdio.h>

/* glibc2 has these functions declared in <stdio.h>.  Avoid redeclarations.  */
-# if __GLIBC__ < 2
+# if !HAVE_WORKING_GETLINE

int getline (char **_lineptr, size_t *_n, FILE *_stream);

+# endif /* ! have getline */
+
+# if !HAVE_GETDELIM
+
int getdelim (char **_lineptr, size_t *_n, int _delimiter, FILE *_stream);

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

#endif /* not GETLINE_H_ */
Index: lib/getnline.c
===================================================================
RCS file: lib/getnline.c
diff -N lib/getnline.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/getnline.c      16 Jul 2003 19:50:47 -0000
@@ -0,0 +1,143 @@
+/* getnline.c -- Implementation of getnline function, a modification of
+   the GNU C library function getline to allow the caller to set a
+   maximum number of characters to be retrieved.
+
+   Copyright (C) 1993, 1996, 1997, 1998, 2000, 2003 Free Software
+   Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* Adapted by Derek Price <derek@ximbiot.com>
+ * from getline.c written by Jan Brittenson <bson@gnu.ai.mit.edu>.
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "getnline.h"
+
+#include <stddef.h>
+#include <stdio.h>
+
+#if STDC_HEADERS
+# include <stdlib.h>
+#else
+char *malloc (), *realloc ();
+#endif
+
+#include "unlocked-io.h"
+
+/* Always add at least this many bytes when extending the buffer.  */
+#define MIN_CHUNK 64
+
+/* 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 *N characters of
+   space.  It is realloc'd as necessary.  Return the number of characters
+   read (not including the NUL terminator), or -1 on error or EOF.  */
+
+static int
+getdelim2( char **lineptr, size_t *n, size_t offset, int limit,
+           int delim1, int delim2, FILE *stream )
+{
+  size_t nchars_avail;         /* Allocated but unused chars in *LINEPTR.  */
+  char *read_pos;              /* Where we're reading into *LINEPTR. */
+  int ret;
+
+  if (!lineptr || !n || !stream)
+    return -1;
+
+  if (!*lineptr)
+    {
+      *n = MIN_CHUNK;
+      *lineptr = malloc (*n);
+      if (!*lineptr)
+       return -1;
+    }
+
+  if (*n < offset)
+    return -1;
+
+  nchars_avail = *n - offset;
+  read_pos = *lineptr + offset;
+
+  for (;;)
+    {
+      register int c;
+
+      if (limit == 0)
+       break;
+
+      c = getc (stream);
+
+      if (limit != GETNLINE_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 (nchars_avail < 2)
+       {
+         if (*n > MIN_CHUNK)
+           *n *= 2;
+         else
+           *n += MIN_CHUNK;
+
+         nchars_avail = *n + *lineptr - read_pos;
+         *lineptr = realloc (*lineptr, *n);
+         if (!*lineptr)
+           return -1;
+         read_pos = *n - nchars_avail + *lineptr;
+       }
+
+      if (c == EOF || ferror (stream))
+       {
+         /* Return partial line, if any.  */
+         if (read_pos == *lineptr)
+           return -1;
+         else
+           break;
+       }
+
+      *read_pos++ = c;
+      nchars_avail--;
+
+      if (c == delim1 || (delim2 && c == delim2))
+       /* Return the line.  */
+       break;
+    }
+
+  /* Done - NUL terminate and return the number of chars read.  */
+  *read_pos = '\0';
+
+  ret = read_pos - (*lineptr + offset);
+  return ret;
+}
+
+
+int
+getnline( char **lineptr, size_t *n, int limit, FILE *stream )
+{
+  return getdelim2( lineptr, n, 0, limit, '\n', 0, stream );
+}
+
+int
+getndelim( char **lineptr, size_t *n, int limit, int delimiter, FILE *stream )
+{
+  return getdelim2( lineptr, n, 0, limit, delimiter, 0, stream );
+}
Index: lib/getnline.h
===================================================================
RCS file: lib/getnline.h
diff -N lib/getnline.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/getnline.h      16 Jul 2003 19:50:47 -0000
@@ -0,0 +1,35 @@
+/* Implementation of getnline function, a version of the GNU C library
+   function getline which allows a maximum number of characters retrieved
+   to be set.
+
+   Copyright (C) 1995, 1997, 1999, 2000, 2001, 2002, 2003 Free
+   Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifndef GETNLINE_H_
+# define GETNLINE_H_ 1
+
+# include <stddef.h>
+# include <stdio.h>
+
+# define GETNLINE_NO_LIMIT -1
+
+int getnline( char **_lineptr, size_t *_n, int limit, FILE *_stream );
+
+int getndelim( char **_lineptr, size_t *_n, int limit, int _delimiter,
+               FILE *_stream );
+
+#endif /* not GETNLINE_H_ */
Index: m4/getline.m4
===================================================================
RCS file: /cvsroot/gnulib/gnulib/m4/getline.m4,v
retrieving revision 1.11
diff -u -r1.11 getline.m4
--- m4/getline.m4       13 Jan 2003 07:08:00 -0000      1.11
+++ m4/getline.m4       16 Jul 2003 19:50:48 -0000
@@ -1,4 +1,4 @@
-# getline.m4 serial 8
+# getline.m4 serial 9

dnl Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software
dnl Foundation, Inc.
@@ -22,9 +22,9 @@

  am_getline_needs_run_time_check=no
  AC_CHECK_FUNC(getline,
-               dnl Found it in some library.  Verify that it works.
-               am_getline_needs_run_time_check=yes,
-               am_cv_func_working_getline=no)
+                dnl Found it in some library.  Verify that it works.
+                am_getline_needs_run_time_check=yes,
+                am_cv_func_working_getline=no)
  if test $am_getline_needs_run_time_check = yes; then
    AC_CACHE_CHECK([for working getline function], am_cv_func_working_getline,
    [echo fooN |tr -d '\012'|tr N '\012' > conftest.data
@@ -49,7 +49,10 @@
    )])
  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.])
+  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.
@@ -63,6 +66,11 @@
# Prerequisites of lib/getline.c.
AC_DEFUN([gl_PREREQ_GETLINE],
[
-  AC_REQUIRE([AC_HEADER_STDC])
-  AC_CHECK_FUNCS(getdelim)
+  AC_CHECK_FUNCS(getdelim,
+                 dnl found it.
+                 gl_have_getdelim=yes,
+                 gl_have_getdelim=no)
+  if test $gl_have_getdelim = no; then
+    gl_PREREQ_GETNLINE
+  fi
])
Index: m4/getnline.m4
===================================================================
RCS file: m4/getnline.m4
diff -N m4/getnline.m4
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ m4/getnline.m4      16 Jul 2003 19:50:48 -0000
@@ -0,0 +1,16 @@
+# getnline.m4 serial 1
+
+dnl Copyright (C) 2003 Free Software Foundation, Inc.
+
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License.  As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+# Prerequisites of lib/getnline.c.
+AC_DEFUN([gl_PREREQ_GETNLINE],
+[
+  AC_REQUIRE([AC_HEADER_STDC])
+  AC_LIBOBJ(getnline)
+])
Index: modules/getline
===================================================================
RCS file: /cvsroot/gnulib/gnulib/modules/getline,v
retrieving revision 1.4
diff -u -r1.4 getline
--- modules/getline     20 Jan 2003 10:02:37 -0000      1.4
+++ modules/getline     16 Jul 2003 19:50:48 -0000
@@ -4,7 +4,10 @@
Files:
lib/getline.h
lib/getline.c
+lib/getnline.h
+lib/getnline.c
m4/getline.m4
+m4/getnline.m4

Depends-on:
unlocked-io
@@ -13,7 +16,7 @@
AM_FUNC_GETLINE

Makefile.am:
-lib_SOURCES += getline.h
+lib_SOURCES += getline.h getnline.h

Include:
"getline.h"
Index: modules/getnline
===================================================================
RCS file: modules/getnline
diff -N modules/getnline
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ modules/getnline    16 Jul 2003 19:50:48 -0000
@@ -0,0 +1,23 @@
+Description:
+Read a line of n characters or less from a stream.
+
+Files:
+lib/getnline.h
+lib/getnline.c
+m4/getnline.m4
+
+Depends-on:
+unlocked-io
+
+configure.ac:
+gl_PREREQ_GETNLINE
+
+Makefile.am:
+lib_SOURCES += getnline.h
+
+Include:
+"getnline.h"
+
+Maintainer:
+all
+



Derek

--
               *8^)

Email: derek@ximbiot.com

Get CVS support at <http://ximbiot.com>!
--
I cannot live without books.

                        - Thomas Jefferson






reply via email to

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