- 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@
This commit is contained in:
David Schultz 2009-02-28 06:00:58 +00:00
parent 8bc369a3e1
commit 69099ba2ec
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=189136
22 changed files with 747 additions and 31 deletions

View file

@ -51,6 +51,17 @@ typedef __size_t size_t;
#define _SIZE_T_DECLARED
#endif
#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200809
#ifndef _OFF_T_DECLARED
#define _OFF_T_DECLARED
typedef __off_t off_t;
#endif
#ifndef _SSIZE_T_DECLARED
#define _SSIZE_T_DECLARED
typedef __ssize_t ssize_t;
#endif
#endif
#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE
#ifndef _VA_LIST_DECLARED
typedef __va_list va_list;
@ -330,6 +341,34 @@ int putw(int, FILE *);
char *tempnam(const char *, const char *);
#endif
#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200809
ssize_t getdelim(char ** __restrict, size_t * __restrict, int,
FILE * __restrict);
/*
* Every programmer and his dog wrote functions called getline()
* before POSIX.1-2008 came along and decided to usurp the name, so we
* don't prototype getline() by default unless one of the following is true:
* a) the app has requested it specifically by defining _WITH_GETLINE
* b) the app has requested a POSIX.1-2008 environment via _POSIX_C_SOURCE
* c) the app defines a GNUism such as _BSD_SOURCE or _GNU_SOURCE
*/
#ifndef _WITH_GETLINE
#if defined(_BSD_SOURCE) || defined(_GNU_SOURCE)
#define _WITH_GETLINE
#elif defined(_POSIX_C_SOURCE)
#if _POSIX_C_SOURCE > 200809
#define _WITH_GETLINE
#endif
#endif
#endif
#ifdef _WITH_GETLINE
ssize_t getline(char ** __restrict, size_t * __restrict, FILE * __restrict);
#endif
#endif /* __BSD_VISIBLE || __POSIX_VISIBLE >= 200809 */
/*
* Routines that are purely local.
*/

View file

@ -67,8 +67,11 @@ void *memmem(const void *, size_t, const void *, size_t) __pure;
#endif
void *memmove(void *, const void *, size_t);
void *memset(void *, int, size_t);
#if __POSIX_VISIBLE >= 200809 || __BSD_VISIBLE
char *stpcpy(char * __restrict, const char * __restrict);
char *stpncpy(char * __restrict, const char * __restrict, size_t);
#endif
#if __BSD_VISIBLE
char *stpcpy(char *, const char *);
char *strcasestr(const char *, const char *) __pure;
#endif
char *strcat(char * __restrict, const char * __restrict);
@ -95,14 +98,19 @@ void strmode(int, char *);
char *strncat(char * __restrict, const char * __restrict, size_t);
int strncmp(const char *, const char *, size_t) __pure;
char *strncpy(char * __restrict, const char * __restrict, size_t);
#if __BSD_VISIBLE
#if __POSIX_VISIBLE >= 200809 || __BSD_VISIBLE
char *strndup(const char *, size_t) __malloc_like;
size_t strnlen(const char *, size_t) __pure;
#endif
#if __BSD_VISIBLE
char *strnstr(const char *, const char *, size_t) __pure;
#endif
char *strpbrk(const char *, const char *) __pure;
char *strrchr(const char *, int) __pure;
#if __BSD_VISIBLE
char *strsep(char **, const char *);
#endif
#if __POSIX_VISIBLE >= 200809 || __BSD_VISIBLE
char *strsignal(int);
#endif
size_t strspn(const char *, const char *) __pure;

View file

@ -210,13 +210,19 @@ int wcwidth(wchar_t);
#define wcwidth(_c) __wcwidth(_c)
#endif
#if __BSD_VISIBLE
wchar_t *fgetwln(struct __sFILE * __restrict, size_t * __restrict);
#if __POSIX_VISIBLE >= 200809 || __BSD_VISIBLE
size_t mbsnrtowcs(wchar_t * __restrict, const char ** __restrict, size_t,
size_t, mbstate_t * __restrict);
wchar_t *wcsdup(const wchar_t *) __malloc_like;
int wcscasecmp(const wchar_t *, const wchar_t *);
int wcsncasecmp(const wchar_t *, const wchar_t *, size_t n);
size_t wcsnlen(const wchar_t *, size_t) __pure;
size_t wcsnrtombs(char * __restrict, const wchar_t ** __restrict, size_t,
size_t, mbstate_t * __restrict);
#endif
#if __BSD_VISIBLE
wchar_t *fgetwln(struct __sFILE * __restrict, size_t * __restrict);
size_t wcslcat(wchar_t *, const wchar_t *, size_t);
size_t wcslcpy(wchar_t *, const wchar_t *, size_t);
#endif

View file

@ -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 \

View file

@ -110,6 +110,11 @@ FBSD_1.0 {
wscanf;
};
FBSD_1.1 {
getdelim;
getline;
};
FBSDprivate_1.0 {
_flockfile;
_flockfile_debug_stub;

View file

@ -116,6 +116,7 @@ or
.Xr fgets 3 ,
.Xr fgetwln 3 ,
.Xr fopen 3 ,
.Xr getline 3 ,
.Xr putc 3
.Sh HISTORY
The

View file

@ -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

158
lib/libc/stdio/getdelim.c Normal file
View file

@ -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);
}

164
lib/libc/stdio/getline.3 Normal file
View file

@ -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 .

39
lib/libc/stdio/getline.c Normal file
View file

@ -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));
}

View file

@ -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"

View file

@ -8,14 +8,16 @@ CFLAGS+= -I${.CURDIR}/locale
# machine-independent string sources
MISRCS+=bcmp.c bcopy.c bzero.c ffs.c ffsl.c ffsll.c fls.c flsl.c flsll.c \
index.c memccpy.c memchr.c memrchr.c memcmp.c \
memcpy.c memmem.c memmove.c memset.c rindex.c stpcpy.c strcasecmp.c \
memcpy.c memmem.c memmove.c memset.c rindex.c \
stpcpy.c stpncpy.c strcasecmp.c \
strcat.c strcasestr.c strchr.c strcmp.c strcoll.c strcpy.c strcspn.c \
strdup.c strerror.c strlcat.c strlcpy.c strlen.c strmode.c strncat.c \
strncmp.c strncpy.c strndup.c strnstr.c \
strncmp.c strncpy.c strndup.c strnlen.c strnstr.c \
strpbrk.c strrchr.c strsep.c strsignal.c strspn.c strstr.c strtok.c \
strxfrm.c swab.c wcscat.c wcschr.c wcscmp.c wcscoll.c wcscpy.c \
wcscspn.c wcsdup.c \
wcslcat.c wcslcpy.c wcslen.c wcsncat.c wcsncmp.c wcsncpy.c wcspbrk.c \
strxfrm.c swab.c wcscasecmp.c wcscat.c \
wcschr.c wcscmp.c wcscoll.c wcscpy.c wcscspn.c wcsdup.c \
wcslcat.c wcslcpy.c wcslen.c wcsncasecmp.c wcsncat.c wcsncmp.c \
wcsncpy.c wcsnlen.c wcspbrk.c \
wcsrchr.c wcsspn.c wcsstr.c wcstok.c wcswidth.c wcsxfrm.c wmemchr.c \
wmemcmp.c \
wmemcpy.c wmemmove.c wmemset.c
@ -47,6 +49,7 @@ MLINKS+=strcat.3 strncat.3
MLINKS+=strchr.3 strrchr.3
MLINKS+=strcmp.3 strncmp.3
MLINKS+=strcpy.3 stpcpy.3 \
strcpy.3 stpncpy.3 \
strcpy.3 strncpy.3
MLINKS+=strdup.3 strndup.3
MLINKS+=strerror.3 perror.3 \
@ -54,10 +57,12 @@ MLINKS+=strerror.3 perror.3 \
strerror.3 sys_errlist.3 \
strerror.3 sys_nerr.3
MLINKS+=strlcpy.3 strlcat.3
MLINKS+=strlen.3 strnlen.3
MLINKS+=strstr.3 strcasestr.3 \
strstr.3 strnstr.3
MLINKS+=strtok.3 strtok_r.3
MLINKS+=wmemchr.3 wcscat.3 \
MLINKS+=wmemchr.3 wcscasecmp.3 \
wmemchr.3 wcscat.3 \
wmemchr.3 wcschr.3 \
wmemchr.3 wcscmp.3 \
wmemchr.3 wcscpy.3 \
@ -66,9 +71,11 @@ MLINKS+=wmemchr.3 wcscat.3 \
wmemchr.3 wcslcat.3 \
wmemchr.3 wcslcpy.3 \
wmemchr.3 wcslen.3 \
wmemchr.3 wcsncasecmp.3 \
wmemchr.3 wcsncat.3 \
wmemchr.3 wcsncmp.3 \
wmemchr.3 wcsncpy.3 \
wmemchr.3 wcsnlen.3 \
wmemchr.3 wcspbrk.3 \
wmemchr.3 wcsrchr.3 \
wmemchr.3 wcsspn.3 \

View file

@ -81,7 +81,12 @@ FBSD_1.1 {
ffsll;
flsll;
memrchr;
stpncpy;
strndup;
strnlen;
wcscasecmp;
wcsncasecmp;
wcsnlen;
};
FBSDprivate_1.0 {

45
lib/libc/string/stpncpy.c Normal file
View file

@ -0,0 +1,45 @@
/*-
* 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 <string.h>
char *
stpncpy(char * __restrict dst, const char * __restrict src, size_t n)
{
for (; n--; dst++, src++) {
if (!(*dst = *src)) {
char *ret = dst;
while (n--)
*++dst = '\0';
return (ret);
}
}
return (dst);
}

View file

@ -32,18 +32,20 @@
.\" @(#)strcpy.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
.Dd August 9, 2001
.Dd February 28, 2009
.Dt STRCPY 3
.Os
.Sh NAME
.Nm strcpy , strncpy
.Nm stpcpy, stpncpy, strcpy , strncpy
.Nd copy strings
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In string.h
.Ft char *
.Fn stpcpy "char *dst" "const char *src"
.Fn stpcpy "char * restrict dst" "const char * restrict src"
.Ft char *
.Fn stpncpy "char * restrict dst" "const char * restrict src" "size_t len"
.Ft char *
.Fn strcpy "char * restrict dst" "const char * restrict src"
.Ft char *
@ -63,8 +65,10 @@ to
character.)
.Pp
The
.Fn stpncpy
and
.Fn strncpy
function copies at most
functions copy at most
.Fa len
characters from
.Fa src
@ -95,10 +99,21 @@ return
.Fa dst .
The
.Fn stpcpy
function returns a pointer to the terminating
and
.Fn stpncpy
functions return a pointer to the terminating
.Ql \e0
character of
.Fa dst .
If
.Fn stpncpy
does not terminate
.Fa dst
with a
.Dv NUL
character, it instead returns a pointer to
.Li dst[n]
(which does not necessarily refer to a valid memory location.)
.Sh EXAMPLES
The following sets
.Va chararray
@ -185,14 +200,16 @@ conform to
.St -isoC .
The
.Fn stpcpy
function is an MS-DOS and GNUism.
The
.Fn stpcpy
function
conforms to no standard.
and
.Fn stpncpy
functions conform to
.St -p1003.1-2008 .
.Sh HISTORY
The
.Fn stpcpy
function first appeared in
.Fx 4.4 ,
coming from 1998-vintage Linux.
and
.Fn stpncpy
was added in
.Fx 8.0 .

View file

@ -32,11 +32,11 @@
.\" @(#)strlen.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
.Dd June 4, 1993
.Dd February 28, 2009
.Dt STRLEN 3
.Os
.Sh NAME
.Nm strlen
.Nm strlen, strnlen
.Nd find length of string
.Sh LIBRARY
.Lb libc
@ -44,12 +44,22 @@
.In string.h
.Ft size_t
.Fn strlen "const char *s"
.Ft size_t
.Fn strnlen "const char *s" "size_t maxlen"
.Sh DESCRIPTION
The
.Fn strlen
function
computes the length of the string
.Fa s .
The
.Fn strnlen
function attempts to compute the length of
.Fa s ,
but never scans beyond the first
.Fa maxlen
bytes of
.Fa s .
.Sh RETURN VALUES
The
.Fn strlen
@ -59,6 +69,13 @@ the number of characters that precede the
terminating
.Dv NUL
character.
The
.Fn strnlen
function returns either the same result as
.Fn strlen
or
.Fa maxlen ,
whichever is smaller.
.Sh SEE ALSO
.Xr string 3
.Sh STANDARDS
@ -67,3 +84,7 @@ The
function
conforms to
.St -isoC .
The
.Fn strnlen
function conforms to
.St -p1003.1-2008 .

42
lib/libc/string/strnlen.c Normal file
View file

@ -0,0 +1,42 @@
/*-
* 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 <string.h>
size_t
strnlen(const char *s, size_t maxlen)
{
size_t len;
for (len = 0; len < maxlen; len++, s++) {
if (!*s)
break;
}
return (len);
}

View file

@ -0,0 +1,45 @@
/*-
* 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 <wchar.h>
#include <wctype.h>
int
wcscasecmp(const wchar_t *s1, const wchar_t *s2)
{
wchar_t c1, c2;
for (; *s1; s1++, s2++) {
c1 = towlower(*s1);
c2 = towlower(*s2);
if (c1 != c2)
return ((int)c1 - c2);
}
return (-*s2);
}

View file

@ -0,0 +1,49 @@
/*-
* 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 <wchar.h>
#include <wctype.h>
int
wcsncasecmp(const wchar_t *s1, const wchar_t *s2, size_t n)
{
wchar_t c1, c2;
if (n == 0)
return (0);
for (; *s1; s1++, s2++) {
c1 = towlower(*s1);
c2 = towlower(*s2);
if (c1 != c2)
return ((int)c1 - c2);
if (--n == 0)
return (0);
}
return (-*s2);
}

42
lib/libc/string/wcsnlen.c Normal file
View file

@ -0,0 +1,42 @@
/*-
* 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 <wchar.h>
size_t
wcsnlen(const wchar_t *s, size_t maxlen)
{
size_t len;
for (len = 0; len < maxlen; len++, s++) {
if (!*s)
break;
}
return (len);
}

View file

@ -35,7 +35,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd August 13, 2005
.Dd February 28, 2009
.Dt WMEMCHR 3
.Os
.Sh NAME
@ -44,6 +44,7 @@
.Nm wmemcpy ,
.Nm wmemmove ,
.Nm wmemset ,
.Nm wcscasecmp ,
.Nm wcscat ,
.Nm wcschr ,
.Nm wcscmp ,
@ -53,9 +54,11 @@
.Nm wcslcat ,
.Nm wcslcpy ,
.Nm wcslen ,
.Nm wcsncasecmp ,
.Nm wcsncat ,
.Nm wcsncmp ,
.Nm wcsncpy ,
.Nm wcsnlen ,
.Nm wcspbrk ,
.Nm wcsrchr ,
.Nm wcsspn ,
@ -75,6 +78,8 @@
.Fn wmemmove "wchar_t *s1" "const wchar_t *s2" "size_t n"
.Ft wchar_t *
.Fn wmemset "wchar_t *s" "wchar_t c" "size_t n"
.Ft int
.Fn wcscasecmp "const wchar_t *s1" "const wchar_t *s2"
.Ft wchar_t *
.Fn wcscat "wchar_t * restrict s1" "const wchar_t * restrict s2"
.Ft wchar_t *
@ -93,12 +98,16 @@
.Fn wcslcpy "wchar_t *s1" "const wchar_t *s2" "size_t n"
.Ft size_t
.Fn wcslen "const wchar_t *s"
.Ft int
.Fn wcsncasecmp "const wchar_t *s1" "const wchar_t *s2" "size_t n"
.Ft wchar_t *
.Fn wcsncat "wchar_t * restrict s1" "const wchar_t * restrict s2" "size_t n"
.Ft int
.Fn wcsncmp "const wchar_t *s1" "const wchar_t * s2" "size_t n"
.Ft wchar_t *
.Fn wcsncpy "wchar_t * restrict s1" "const wchar_t * restrict s2" "size_t n"
.Ft size_t
.Fn wcsnlen "const wchar_t *s" "size_t maxlen"
.Ft wchar_t *
.Fn wcspbrk "const wchar_t *s1" "const wchar_t *s2"
.Ft wchar_t *
@ -119,6 +128,7 @@ counterpart, such as
.Xr memcpy 3 ,
.Xr memmove 3 ,
.Xr memset 3 ,
.Xr strcasecmp 3 ,
.Xr strcat 3 ,
.Xr strchr 3 ,
.Xr strcmp 3 ,
@ -131,6 +141,7 @@ counterpart, such as
.Xr strncat 3 ,
.Xr strncmp 3 ,
.Xr strncpy 3 ,
.Xr strnlen 3 ,
.Xr strpbrk 3 ,
.Xr strrchr 3 ,
.Xr strspn 3 ,
@ -139,8 +150,15 @@ counterpart, such as
These functions conform to
.St -isoC-99 ,
with the exception of
.Fn wcscasecmp ,
.Fn wcsdup ,
.Fn wcslcat ,
.Fn wcsncasecmp ,
and
.Fn wcsnlen ,
which conform to
.St -p1003.1-2008 ;
and
.Fn wcslcat
and
.Fn wcslcpy ,
which are extensions.

View file

@ -57,7 +57,7 @@
* is created, otherwise 1.
*/
#undef __FreeBSD_version
#define __FreeBSD_version 800066 /* Master, propagated to newvers */
#define __FreeBSD_version 800067 /* Master, propagated to newvers */
#ifndef LOCORE
#include <sys/types.h>