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