tech-userlevel archive

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

adding getdelim(3) and getline(3) to libc



Our libc lacks getdelim(3) and getline(3) which are in POSIX IEEE Std 1003.1-2008
http://www.opengroup.org/onlinepubs/9699919799/functions/getline.html

Attached is patch to add these fucntions and man page to our libc.
I've not extensively tested it, but it seems to work fine.

The only issue is that getline collides with quite a few userland bits such as ctags and nawk. I propose we change their internal definitons to get_line, unless the really implement their own getline(3) and we can just remove it.

Comments?

Thanks

Roy
Index: lib/libc/stdio/getdelim.c
===================================================================
RCS file: lib/libc/stdio/getdelim.c
diff -N lib/libc/stdio/getdelim.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libc/stdio/getdelim.c   12 Jul 2009 22:29:37 -0000
@@ -0,0 +1,111 @@
+/* $NetBSD: $ */
+
+/*
+ * Copyright (c) 2009 The NetBSD Foundation, Inc.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Roy Marples.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if !defined(lint)
+__RCSID("$NetBSD: fgetstr.c,v 1.5 2009/01/31 06:14:13 lukem Exp $");
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "reentrant.h"
+#include "local.h"
+
+ssize_t
+getdelim(char **__restrict buf, size_t *__restrict buflen,
+    int sep, FILE *__restrict fp)
+{
+       unsigned char *p;
+       ssize_t len, off;
+       char *newb;
+
+       _DIAGASSERT(buf != NULL);
+       _DIAGASSERT(bufsiz != NULL);
+       _DIAGASSERT(fp != NULL);
+
+       if (buf == NULL || buflen == NULL) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       FLOCKFILE(fp);
+       _SET_ORIENTATION(fp, -1);
+       off = 0;
+       for (;;) {
+               /* If the buffer is empty, refill it. */
+               if (fp->_r <= 0) {
+                       if (__srefill(fp)) {
+                               /* EOF/error: stop with partial or no line */
+                               if (off == 0) {
+                                       FUNLOCKFILE(fp);
+                                       return -1;
+                               }
+                               break;
+                       }
+               }
+
+               /* Scan through looking for the seperator. */
+               p = memchr(fp->_p, sep, fp->_r);
+               if (p == NULL)
+                       len = fp->_r;
+               else
+                       len = (p - fp->_p) + 1;
+
+               /* Ensure that the resultant buffer length fits in ssize_t */
+               if (off + len + 1 < off) {
+                       FUNLOCKFILE(fp);
+                       errno = EOVERFLOW;
+                       return -1;
+               }
+               /* Ensure our buffer is large enough, including a terminator */
+               if ((size_t)(off + len + 1) > *buflen) {
+                       newb = realloc(*buf, off + len + 1);
+                       if (newb == NULL) {
+                               FUNLOCKFILE(fp);
+                               return -1;
+                       }
+                       *buf = newb;
+                       *buflen = off + len;
+               }
+
+               (void)memcpy((void *)(*buf + off), (void *)fp->_p, len);
+               fp->_r -= len;
+               fp->_p += len;
+               off += len;
+               if (p != NULL)
+                       break;
+       }
+       FUNLOCKFILE(fp);
+       if (*buf != NULL)
+               *(*buf + off) = '\0';
+       return off;
+}
Index: lib/libc/stdio/getline.c
===================================================================
RCS file: lib/libc/stdio/getline.c
diff -N lib/libc/stdio/getline.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libc/stdio/getline.c    12 Jul 2009 22:29:37 -0000
@@ -0,0 +1,46 @@
+/* $NetBSD: $ */
+
+/*
+ * Copyright (c) 2009 The NetBSD Foundation, Inc.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Roy Marples.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if !defined(lint)
+__RCSID("$NetBSD: fgetln.c,v 1.14 2004/05/10 16:47:11 drochner Exp $");
+#endif
+
+#include "namespace.h"
+
+#include <stdio.h>
+
+#include "reentrant.h"
+#include "local.h"
+
+ssize_t
+getline(char **__restrict buf, size_t *__restrict buflen, FILE *__restrict fp)
+{
+       return getdelim(buf, buflen, '\n', fp);
+}
Index: lib/libc/stdio/getdelim.3
===================================================================
RCS file: lib/libc/stdio/getdelim.3
diff -N lib/libc/stdio/getdelim.3
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/libc/stdio/getdelim.3   12 Jul 2009 22:29:37 -0000
@@ -0,0 +1,118 @@
+.\"     $NetBSD: Exp $
+.\"
+.\" Copyright (c) 2009 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Roy Marples.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd July 12, 2009
+.Dt GETDELIM 3
+.Os
+.Sh NAME
+.Nm getdelim ,
+.Nm getline
+.Nd read a delimited record from input stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft ssize_t
+.Fn getdelim "char ** restrict lineptr" "size_t * restrict n" "int delimiter" 
"FILE * restrict stream"
+.Ft ssize_t
+.Fn getdeline "char ** restrict lineptr" "size_t * restrict n" "FILE * 
restrict stream"
+.Sh DESCRIPTION
+The
+.Fn getdelim
+function reads from the input
+.Fa stream
+until it encounters a character matching the
+.Fa delimiter
+character, storing the input in
+.Fa *lineptr .
+The buffer is
+.Dv NULL
+terminated and includes the delimiter.
+.Pp
+If
+.Fa *n
+is non zero, then
+.Fa *lineptr
+must be pre-allocated to at least
+.Fa *n
+bytes.
+.Fn getdelim
+enures that
+.Fa *lineptr
+is large enough to hold the input, updating
+.Fa *n
+to reflect the new size.
+.Pp
+.Fa getline
+is equivalent to
+.Fa getdelim
+with the delimiter set to the newline character.
+.Sh RETURN VALUES
+The
+.Fn getdelim
+function return the number of characters read, including the delimiter.
+If an error occurs the function return -1 and the global variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+.Bl -tag -width [EOVERFLOW]
+.It Bq Er EINVAL
+.Fa *lineptr
+or
+.Fa *n
+is a
+.Dv NULL
+pointer.
+.It Bq Er EOVERFLOW
+More than ssize_t characters were read without encountering the delimiter.
+.El
+.Pp
+The
+.Fn getdelim
+function may also fail and set
+.Va errno
+for any of the errors specified in the routines
+.Xr fflush 3 ,
+.Xr malloc 3 ,
+.Xr read 2 ,
+.Xr stat 2
+or
+.Xr realloc 3 .
+.Sh SEE ALSO
+.Xr ferror 3 ,
+.Xr fgets 3 ,
+.Xr fopen 3 .
+.Sh STANDARDS
+The
+.Fn getdelim
+and
+.Fn getline
+functions
+conform to 
+.St -p1003.1-2008
Index: lib/libc/stdio/Makefile.inc
===================================================================
RCS file: /cvsroot/src/lib/libc/stdio/Makefile.inc,v
retrieving revision 1.35
diff -u -p -r1.35 Makefile.inc
--- lib/libc/stdio/Makefile.inc 3 Feb 2007 00:28:56 -0000       1.35
+++ lib/libc/stdio/Makefile.inc 12 Jul 2009 22:29:37 -0000
@@ -12,10 +12,10 @@ SRCS+=      asprintf.c clrerr.c fclose.c fdop
        fprintf.c fpurge.c fputc.c fputs.c fputwc.c fputws.c fread.c \
        freopen.c fscanf.c fseek.c fseeko.c fsetpos.c ftell.c ftello.c \
        funopen.c fvwrite.c fwalk.c fwide.c fwprintf.c fwrite.c fwscanf.c \
-       getc.c getchar.c gettemp.c getw.c getwc.c getwchar.c makebuf.c \
-       mkdtemp.c mkstemp.c perror.c printf.c putc.c putchar.c puts.c \
-       putw.c putwc.c putwchar.c refill.c remove.c rewind.c rget.c \
-       scanf.c setbuf.c setbuffer.c setvbuf.c snprintf.c snprintf_ss.c \
+       getc.c getchar.c getdelim.c getline.c gettemp.c getw.c getwc.c \
+       getwchar.c makebuf.c mkdtemp.c mkstemp.c perror.c printf.c putc.c \
+       putchar.c puts.c putw.c putwc.c putwchar.c refill.c remove.c rewind.c \
+       rget.c scanf.c setbuf.c setbuffer.c setvbuf.c snprintf.c snprintf_ss.c \
        sscanf.c stdio.c swprintf.c swscanf.c tmpfile.c ungetc.c ungetwc.c \
        vasprintf.c vfprintf.c vfscanf.c vfwprintf.c vfwscanf.c vprintf.c \
        vscanf.c vsnprintf.c vsnprintf_ss.c vsscanf.c vswprintf.c vswscanf.c \
@@ -30,7 +30,7 @@ SRCS+=        _fileno.c _fseeko.c _ftello.c
 
 MAN+=  fclose.3 ferror.3 fflush.3 fgetln.3 fgets.3 fgetwln.3 fgetws.3 \
        flockfile.3 fopen.3 fparseln.3 fputs.3 fputws.3 fread.3 fseek.3 \
-       funopen.3 fwide.3 getc.3 getwc.3 mktemp.3 printf.3 \
+       funopen.3 fwide.3 getc.3 getdelim.3 getwc.3 mktemp.3 printf.3 \
        putc.3 putwc.3 remove.3 scanf.3 setbuf.3 stdio.3 tmpnam.3 \
        ungetc.3 ungetwc.3 wprintf.3 wscanf.3
 
@@ -46,6 +46,7 @@ MLINKS+=fseek.3 fgetpos.3 fseek.3 fseeko
 MLINKS+=funopen.3 fropen.3 funopen.3 fwopen.3
 MLINKS+=getc.3 fgetc.3 getc.3 getc_unlocked.3 getc.3 getchar.3 \
        getc.3 getchar_unlocked.3 getc.3 getw.3
+MLINKS+=getdelim.3 getline.3
 MLINKS+=mktemp.3 mkdtemp.3 mktemp.3 mkstemp.3
 MLINKS+=printf.3 asprintf.3 printf.3 fprintf.3 printf.3 snprintf.3 \
        printf.3 sprintf.3 printf.3 vasprintf.3 printf.3 vfprintf.3 \
Index: include/stdio.h
===================================================================
RCS file: /cvsroot/src/include/stdio.h,v
retrieving revision 1.73
diff -u -p -r1.73 stdio.h
--- include/stdio.h     21 Sep 2008 16:59:46 -0000      1.73
+++ include/stdio.h     12 Jul 2009 22:29:38 -0000
@@ -46,6 +46,10 @@
 typedef        _BSD_SIZE_T_    size_t;
 #undef _BSD_SIZE_T_
 #endif
+#ifdef _BSD_SSIZE_T_
+typedef        _BSD_SSIZE_T_   ssize_t;
+#undef _BSD_SSIZE_T_
+#endif
 
 #include <sys/null.h>
 
@@ -236,6 +240,9 @@ long         ftell(FILE *);
 size_t  fwrite(const void * __restrict, size_t, size_t, FILE * __restrict);
 int     getc(FILE *);
 int     getchar(void);
+ssize_t         getdelim(char ** __restrict, size_t * __restrict, int,
+           FILE * __restrict);
+ssize_t         getline(char ** __restrict, size_t * __restrict, FILE * 
__restrict);
 void    perror(const char *);
 int     printf(const char * __restrict, ...)
     __attribute__((__format__(__printf__, 1, 2)));


Home | Main Index | Thread Index | Old Index