On Sun, Jul 12, 2009 at 11:46:57PM +0100, Roy Marples wrote:
> 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.
I'd add some appropriate tests in regress/lib/libc/stdio (?)
to go with this.
> 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.
Rename theirs is probably the way to go -- they'll have problems
on other modern POSIX systems anyway.
> Comments?
More inline.
| 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: $ */
Convert this to "$NetBSD$" so it gets expanded correctly.
| +#include <sys/cdefs.h>
| +#if !defined(lint)
| +__RCSID("$NetBSD: fgetstr.c,v 1.5 2009/01/31 06:14:13 lukem Exp $");
| +#endif
Convert this to "$NetBSD$" before checkin (just as a matter of style).
| +#include <assert.h>
| +#include <errno.h>
| +#include <stdio.h>
| +#include <stdlib.h>
| +#include <string.h>
| +#include "reentrant.h"
| +#include "local.h"
Add a blank line after <string.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);
Arguably these aren't necessary when the function explicitly
checks the parameters, as it does below.
| + _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. */
"separator"
| + 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: $ */
Same change as for getdelim.c
| +#include <sys/cdefs.h>
| +#if !defined(lint)
| +__RCSID("$NetBSD: fgetln.c,v 1.14 2004/05/10 16:47:11 drochner Exp $");
| +#endif
Same change as for getdelim.c
| 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 $
Oops!
| +.\"
| +.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"
This should be "getline" not "getdeline"
I suggest that you update stdio(3) for these methods.
cheers,
Luke.
Attachment:
pgptEdgWIiLNc.pgp
Description: PGP signature