summaryrefslogtreecommitdiffstats
path: root/lib/libc/stdio
diff options
context:
space:
mode:
authordas <das@FreeBSD.org>2009-02-28 06:00:58 +0000
committerdas <das@FreeBSD.org>2009-02-28 06:00:58 +0000
commita67fbaa46cbdf18a03eefb3f83e2f74f68918753 (patch)
treef258384b92d5c4bde23e95d4c44fa3547a0364cd /lib/libc/stdio
parentb739b3fb48f28ef6b6e7efeeceb832d3dec3fc9c (diff)
downloadFreeBSD-src-a67fbaa46cbdf18a03eefb3f83e2f74f68918753.zip
FreeBSD-src-a67fbaa46cbdf18a03eefb3f83e2f74f68918753.tar.gz
- Add getdelim(), getline(), stpncpy(), strnlen(), wcsnlen(),
wcscasecmp(), and wcsncasecmp(). - Make some previously non-standard extensions visible if POSIX_VISIBLE >= 200809. - Use restrict qualifiers in stpcpy(). - Declare off_t and size_t in stdio.h. - Bump __FreeBSD_version in case the new symbols (particularly getline()) cause issues with ports. Reviewed by: standards@
Diffstat (limited to 'lib/libc/stdio')
-rw-r--r--lib/libc/stdio/Makefile.inc8
-rw-r--r--lib/libc/stdio/Symbol.map5
-rw-r--r--lib/libc/stdio/fgetln.31
-rw-r--r--lib/libc/stdio/fgets.33
-rw-r--r--lib/libc/stdio/getdelim.c158
-rw-r--r--lib/libc/stdio/getline.3164
-rw-r--r--lib/libc/stdio/getline.c39
-rw-r--r--lib/libc/stdio/stdio.34
8 files changed, 377 insertions, 5 deletions
diff --git a/lib/libc/stdio/Makefile.inc b/lib/libc/stdio/Makefile.inc
index fc106db..2ed62f5 100644
--- a/lib/libc/stdio/Makefile.inc
+++ b/lib/libc/stdio/Makefile.inc
@@ -10,8 +10,8 @@ SRCS+= _flock_stub.c asprintf.c clrerr.c fclose.c fcloseall.c fdopen.c \
fileno.c findfp.c flags.c fopen.c fprintf.c fpurge.c fputc.c fputs.c \
fputwc.c fputws.c fread.c freopen.c fscanf.c fseek.c fsetpos.c \
ftell.c funopen.c fvwrite.c fwalk.c fwide.c fwprintf.c fwscanf.c \
- fwrite.c getc.c \
- getchar.c gets.c getw.c getwc.c getwchar.c makebuf.c mktemp.c \
+ fwrite.c getc.c getchar.c getdelim.c getline.c \
+ gets.c getw.c getwc.c getwchar.c makebuf.c mktemp.c \
perror.c printf.c printf-pos.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 \
@@ -33,7 +33,8 @@ SYM_MAPS+= ${.CURDIR}/stdio/Symbol.map
MAN+= fclose.3 ferror.3 fflush.3 fgetln.3 fgets.3 fgetwln.3 fgetws.3 \
flockfile.3 \
fopen.3 fputs.3 \
- fputws.3 fread.3 fseek.3 funopen.3 fwide.3 getc.3 getwc.3 mktemp.3 \
+ fputws.3 fread.3 fseek.3 funopen.3 fwide.3 getc.3 \
+ getline.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
@@ -53,6 +54,7 @@ MLINKS+=fseek.3 fgetpos.3 fseek.3 fseeko.3 fseek.3 fsetpos.3 fseek.3 ftell.3 \
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+=getline.3 getdelim.3
MLINKS+=getwc.3 fgetwc.3 getwc.3 getwchar.3
MLINKS+=mktemp.3 mkdtemp.3 mktemp.3 mkstemp.3 mktemp.3 mkstemps.3
MLINKS+=printf.3 asprintf.3 printf.3 fprintf.3 \
diff --git a/lib/libc/stdio/Symbol.map b/lib/libc/stdio/Symbol.map
index ac93cb2..bf054b6 100644
--- a/lib/libc/stdio/Symbol.map
+++ b/lib/libc/stdio/Symbol.map
@@ -110,6 +110,11 @@ FBSD_1.0 {
wscanf;
};
+FBSD_1.1 {
+ getdelim;
+ getline;
+};
+
FBSDprivate_1.0 {
_flockfile;
_flockfile_debug_stub;
diff --git a/lib/libc/stdio/fgetln.3 b/lib/libc/stdio/fgetln.3
index b95c61e..4b83664 100644
--- a/lib/libc/stdio/fgetln.3
+++ b/lib/libc/stdio/fgetln.3
@@ -116,6 +116,7 @@ or
.Xr fgets 3 ,
.Xr fgetwln 3 ,
.Xr fopen 3 ,
+.Xr getline 3 ,
.Xr putc 3
.Sh HISTORY
The
diff --git a/lib/libc/stdio/fgets.3 b/lib/libc/stdio/fgets.3
index cd74fcc..aa8e2ac 100644
--- a/lib/libc/stdio/fgets.3
+++ b/lib/libc/stdio/fgets.3
@@ -147,7 +147,8 @@ the FSA.)
.Xr feof 3 ,
.Xr ferror 3 ,
.Xr fgetln 3 ,
-.Xr fgetws 3
+.Xr fgetws 3 ,
+.Xr getline 3
.Sh STANDARDS
The functions
.Fn fgets
diff --git a/lib/libc/stdio/getdelim.c b/lib/libc/stdio/getdelim.c
new file mode 100644
index 0000000..fb02889
--- /dev/null
+++ b/lib/libc/stdio/getdelim.c
@@ -0,0 +1,158 @@
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * 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 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 AUTHOR 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+#include "local.h"
+
+static inline size_t
+p2roundup(size_t n)
+{
+
+ if (!powerof2(n)) {
+ n--;
+ n |= n >> 1;
+ n |= n >> 2;
+ n |= n >> 4;
+ n |= n >> 8;
+ n |= n >> 16;
+#if SIZE_T_MAX > 0xffffffffU
+ n |= n >> 32;
+#endif
+ n++;
+ }
+ return (n);
+}
+
+/*
+ * Expand *linep to hold len bytes (up to SSIZE_MAX + 1).
+ */
+static inline int
+expandtofit(char ** __restrict linep, size_t len, size_t * __restrict capp)
+{
+ char *newline;
+ size_t newcap;
+
+ if (len > (size_t)SSIZE_MAX + 1) {
+ errno = EOVERFLOW;
+ return (-1);
+ }
+ if (len > *capp) {
+ if (len == (size_t)SSIZE_MAX + 1) /* avoid overflow */
+ newcap = (size_t)SSIZE_MAX + 1;
+ else
+ newcap = p2roundup(len);
+ newline = realloc(*linep, newcap);
+ if (newline == NULL)
+ return (-1);
+ *capp = newcap;
+ *linep = newline;
+ }
+ return (0);
+}
+
+/*
+ * Append the src buffer to the *dstp buffer. The buffers are of
+ * length srclen and *dstlenp, respectively, and dst has space for
+ * *dstlenp bytes. After the call, *dstlenp and *dstcapp are updated
+ * appropriately, and *dstp is reallocated if needed. Returns 0 on
+ * success, -1 on allocation failure.
+ */
+static int
+sappend(char ** __restrict dstp, size_t * __restrict dstlenp,
+ size_t * __restrict dstcapp, char * __restrict src, size_t srclen)
+{
+
+ /* ensure room for srclen + dstlen + terminating NUL */
+ if (expandtofit(dstp, srclen + *dstlenp + 1, dstcapp))
+ return (-1);
+ memcpy(*dstp + *dstlenp, src, srclen);
+ *dstlenp += srclen;
+ return (0);
+}
+
+ssize_t
+getdelim(char ** __restrict linep, size_t * __restrict linecapp, int delim,
+ FILE * __restrict fp)
+{
+ u_char *endp;
+ size_t linelen;
+
+ FLOCKFILE(fp);
+ ORIENT(fp, -1);
+
+ if (linep == NULL || linecapp == NULL) {
+ errno = EINVAL;
+ goto error;
+ }
+
+ linelen = 0;
+ if (*linecapp == 0)
+ *linep = NULL;
+
+ if (fp->_r <= 0 && __srefill(fp)) {
+ /* If fp is at EOF already, we just need space for the NUL. */
+ if (__sferror(fp) || expandtofit(linep, 1, linecapp))
+ goto error;
+ goto done;
+ }
+
+ while ((endp = memchr(fp->_p, delim, fp->_r)) == NULL) {
+ if (sappend(linep, &linelen, linecapp, fp->_p, fp->_r))
+ goto error;
+ if (__srefill(fp)) {
+ if (__sferror(fp))
+ goto error;
+ goto done; /* hit EOF */
+ }
+ }
+ endp++; /* snarf the delimiter, too */
+ if (sappend(linep, &linelen, linecapp, fp->_p, endp - fp->_p))
+ goto error;
+ fp->_r -= endp - fp->_p;
+ fp->_p = endp;
+done:
+ /* Invariant: *linep has space for at least linelen+1 bytes. */
+ (*linep)[linelen] = '\0';
+ FUNLOCKFILE(fp);
+ return (linelen);
+
+error:
+ fp->_flags |= __SERR;
+ FUNLOCKFILE(fp);
+ return (-1);
+}
diff --git a/lib/libc/stdio/getline.3 b/lib/libc/stdio/getline.3
new file mode 100644
index 0000000..096331a
--- /dev/null
+++ b/lib/libc/stdio/getline.3
@@ -0,0 +1,164 @@
+.\" Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" 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 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 AUTHOR 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.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd February 28, 2009
+.Dt GETLINE 3
+.Os
+.Sh NAME
+.Nm getdelim ,
+.Nm getline
+.Nd get a line from a stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.Fd "#define _WITH_GETLINE"
+.In stdio.h
+.Ft ssize_t
+.Fn getdelim "char ** restrict linep" "size_t * restrict linecapp" "int delimiter" " FILE * restrict stream"
+.Ft ssize_t
+.Fn getline "char ** restrict linep" "size_t * restrict linecapp" " FILE * restrict stream"
+.Sh DESCRIPTION
+The
+.Fn getdelim
+function reads a line from
+.Fa stream ,
+delimited by the character
+.Fa delimiter .
+The
+.Fn getline
+function is equivalent to
+.Fn getdelim
+with the newline character as the delimiter.
+The delimiter character is included as part of the line, unless
+the end of the file is reached.
+The caller may provide a pointer to a malloc buffer for the line in
+.Fa *linep ,
+and the capacity of that buffer in
+.Fa *linecapp ;
+if
+.Fa *linecapp
+is 0, then
+.Fa *linep
+is treated as
+.Dv NULL .
+These functions may expand the buffer as needed, as if via
+.Fn realloc ,
+and update
+.Fa *linep
+and
+.Fa *linecapp
+accordingly.
+.Sh RETURN VALUES
+The
+.Fn getdelim
+and
+.Fn getline
+functions return the number of characters written, excluding the
+terminating
+.Dv NUL .
+The value \-1 is returned if an error occurs.
+.Sh EXAMPLES
+The following code fragment reads lines from a file and
+writes them to standard output.
+The
+.Fn fwrite
+function is used in case the line contains embedded
+.Dv NUL
+characters.
+.Bd -literal -offset indent
+char *line = NULL;
+size_t linecap = 0;
+ssize_t linelen;
+while ((linelen = getline(&line, &linecap, fp)) > 0)
+ fwrite(line, linelen, 1, stdout);
+.Ed
+.Sh COMPATIBILITY
+Many application writers used the name
+.Va getline
+before the
+.Fn getline
+function was introduced in
+.St -p1003.1 ,
+so a prototype is not provided by default in order to avoid
+compatibility problems.
+Applications that wish to use the
+.Fn getline
+function described herein should either request a strict
+.St -p1003.1-2008
+environment by defining the macro
+.Dv _POSIX_C_SOURCE
+to the value 200809 or greater, or by defining the macro
+.Dv _WITH_GETLINE ,
+prior to the inclusion of
+.In stdio.h .
+For compatibility with GNU libc, defining either
+.Dv _BSD_SOURCE
+or
+.Dv _GNU_SOURCE
+prior to the inclusion of
+.In stdio.h
+will also make
+.Fn getline
+available.
+.Sh ERRORS
+These functions may fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Either
+.Fa linep
+or
+.Fa linecapp
+is
+.Dv NULL .
+.It Bq Er EOVERFLOW
+No delimiter was found in the first
+.Dv SSIZE_MAX
+characters.
+.El
+.Pp
+These functions may also fail for any of the errors specified for
+.Fn fgets
+and
+.Fn malloc .
+.Sh SEE ALSO
+.Xr fgetln 3 ,
+.Xr fgets 3 ,
+.Xr malloc 3
+.Sh STANDARDS
+The
+.Fn getdelim
+and
+.Fn getline
+functions conform to
+.St -p1003.1-2008 .
+.Sh HISTORY
+These routines first appeared in
+.Fx 8.0 .
+.Sh BUGS
+There are no wide character versions of
+.Fn getdelim
+or
+.Fn getline .
diff --git a/lib/libc/stdio/getline.c b/lib/libc/stdio/getline.c
new file mode 100644
index 0000000..3f35520
--- /dev/null
+++ b/lib/libc/stdio/getline.c
@@ -0,0 +1,39 @@
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * 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 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 AUTHOR 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define _WITH_GETLINE
+#include <stdio.h>
+
+ssize_t
+getline(char ** __restrict linep, size_t * __restrict linecapp,
+ FILE * __restrict fp)
+{
+
+ return (getdelim(linep, linecapp, '\n', fp));
+}
diff --git a/lib/libc/stdio/stdio.3 b/lib/libc/stdio/stdio.3
index 1a13ee9..a4d1eb7 100644
--- a/lib/libc/stdio/stdio.3
+++ b/lib/libc/stdio/stdio.3
@@ -28,7 +28,7 @@
.\" @(#)stdio.3 8.7 (Berkeley) 4/19/94
.\" $FreeBSD$
.\"
-.Dd January 10, 2003
+.Dd February 28, 2009
.Dt STDIO 3
.Os
.Sh NAME
@@ -276,6 +276,8 @@ library conforms to
.It "fwrite binary stream input/output"
.It "getc get next character or word from input stream"
.It "getchar get next character or word from input stream"
+.It "getdelim get a line from a stream"
+.It "getline get a line from a stream"
.It "gets get a line from a stream"
.It "getw get next character or word from input stream"
.It "getwc get next wide character from input stream"
OpenPOWER on IntegriCloud