1
0
mirror of https://git.savannah.gnu.org/git/gnulib.git synced 2025-08-08 17:22:05 +03:00

New module 'strncat'.

This commit is contained in:
Bruno Haible
2010-04-05 21:14:58 +02:00
parent fb814d4cf9
commit 097fd2f5f5
9 changed files with 221 additions and 4 deletions

View File

@@ -1,3 +1,20 @@
2010-04-05 Bruno Haible <bruno@clisp.org>
New module 'strncat'.
* lib/string.in.h (strncat): New declaration.
* lib/strncat.c: New file, based on lib/unistr/u-strncat.h.
* m4/strncat.m4: New file, based on m4/memchr.m4.
* modules/strncat: New file.
* m4/string_h.m4 (gl_HEADER_STRING_H_BODY): Also check whether strncat
is declared.
(gl_HEADER_STRING_H_DEFAULTS): Initialize GNULIB_STRNCAT,
REPLACE_STRNCAT.
* modules/string (Makefile.am): Substitute GNULIB_STRNCAT,
REPLACE_STRNCAT.
* doc/posix-functions/strncat.texi: Mention the Solaris bug and the new
module.
* tests/test-string-c++.cc: Check signature of strncat.
2010-04-05 Jim Meyering <meyering@redhat.com> 2010-04-05 Jim Meyering <meyering@redhat.com>
xstrtoumax-tests: convert to use init.sh xstrtoumax-tests: convert to use init.sh

View File

@@ -4,10 +4,13 @@
POSIX specification: @url{http://www.opengroup.org/onlinepubs/9699919799/functions/strncat.html} POSIX specification: @url{http://www.opengroup.org/onlinepubs/9699919799/functions/strncat.html}
Gnulib module: --- Gnulib module: strncat
Portability problems fixed by Gnulib: Portability problems fixed by Gnulib:
@itemize @itemize
@item
This function dereferences too much memory on some platforms:
Solaris 10 on SPARC.
@end itemize @end itemize
Portability problems not fixed by Gnulib: Portability problems not fixed by Gnulib:

View File

@@ -320,6 +320,28 @@ _GL_WARN_ON_USE (strdup, "strdup is unportable - "
# endif # endif
#endif #endif
/* Append no more than N characters from SRC onto DEST. */
#if @GNULIB_STRNCAT@
# if @REPLACE_STRNCAT@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef strncat
# define strncat rpl_strncat
# endif
_GL_FUNCDECL_RPL (strncat, char *, (char *dest, const char *src, size_t n)
_GL_ARG_NONNULL ((1, 2)));
_GL_CXXALIAS_RPL (strncat, char *, (char *dest, const char *src, size_t n));
# else
_GL_CXXALIAS_SYS (strncat, char *, (char *dest, const char *src, size_t n));
# endif
_GL_CXXALIASWARN (strncat);
#elif defined GNULIB_POSIXCHECK
# undef strncat
# if HAVE_RAW_DECL_STRNCAT
_GL_WARN_ON_USE (strncat, "strncat is unportable - "
"use gnulib module strncat for portability");
# endif
#endif
/* Return a newly allocated copy of at most N bytes of STRING. */ /* Return a newly allocated copy of at most N bytes of STRING. */
#if @GNULIB_STRNDUP@ #if @GNULIB_STRNDUP@
# if @REPLACE_STRNDUP@ # if @REPLACE_STRNDUP@

33
lib/strncat.c Normal file
View File

@@ -0,0 +1,33 @@
/* Concatenate strings.
Copyright (C) 1999, 2002, 2006, 2010 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2002.
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
/* Specification. */
#include <string.h>
char *
strncat (char *dest, const char *src, size_t n)
{
char *destptr = dest + strlen (dest);
for (; n > 0 && (*destptr = *src) != '\0'; src++, destptr++, n--)
;
if (n == 0)
*destptr = '\0';
return dest;
}

View File

@@ -5,7 +5,7 @@
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved. # with or without modifications, as long as this notice is preserved.
# serial 15 # serial 16
# Written by Paul Eggert. # Written by Paul Eggert.
@@ -26,8 +26,10 @@ AC_DEFUN([gl_HEADER_STRING_H_BODY],
dnl corresponding gnulib module is not in use, and which is not dnl corresponding gnulib module is not in use, and which is not
dnl guaranteed by C89. dnl guaranteed by C89.
gl_WARN_ON_USE_PREPARE([[#include <string.h> gl_WARN_ON_USE_PREPARE([[#include <string.h>
]], [memmem mempcpy memrchr rawmemchr stpcpy stpncpy strchrnul strdup ]],
strndup strnlen strpbrk strsep strcasestr strtok_r strsignal strverscmp]) [memmem mempcpy memrchr rawmemchr stpcpy stpncpy strchrnul strdup
strncat strndup strnlen strpbrk strsep strcasestr strtok_r strsignal
strverscmp])
]) ])
AC_DEFUN([gl_STRING_MODULE_INDICATOR], AC_DEFUN([gl_STRING_MODULE_INDICATOR],
@@ -50,6 +52,7 @@ AC_DEFUN([gl_HEADER_STRING_H_DEFAULTS],
GNULIB_STPNCPY=0; AC_SUBST([GNULIB_STPNCPY]) GNULIB_STPNCPY=0; AC_SUBST([GNULIB_STPNCPY])
GNULIB_STRCHRNUL=0; AC_SUBST([GNULIB_STRCHRNUL]) GNULIB_STRCHRNUL=0; AC_SUBST([GNULIB_STRCHRNUL])
GNULIB_STRDUP=0; AC_SUBST([GNULIB_STRDUP]) GNULIB_STRDUP=0; AC_SUBST([GNULIB_STRDUP])
GNULIB_STRNCAT=0; AC_SUBST([GNULIB_STRNCAT])
GNULIB_STRNDUP=0; AC_SUBST([GNULIB_STRNDUP]) GNULIB_STRNDUP=0; AC_SUBST([GNULIB_STRNDUP])
GNULIB_STRNLEN=0; AC_SUBST([GNULIB_STRNLEN]) GNULIB_STRNLEN=0; AC_SUBST([GNULIB_STRNLEN])
GNULIB_STRPBRK=0; AC_SUBST([GNULIB_STRPBRK]) GNULIB_STRPBRK=0; AC_SUBST([GNULIB_STRPBRK])
@@ -100,6 +103,7 @@ AC_DEFUN([gl_HEADER_STRING_H_DEFAULTS],
REPLACE_STRSTR=0; AC_SUBST([REPLACE_STRSTR]) REPLACE_STRSTR=0; AC_SUBST([REPLACE_STRSTR])
REPLACE_STRCASESTR=0; AC_SUBST([REPLACE_STRCASESTR]) REPLACE_STRCASESTR=0; AC_SUBST([REPLACE_STRCASESTR])
REPLACE_STRERROR=0; AC_SUBST([REPLACE_STRERROR]) REPLACE_STRERROR=0; AC_SUBST([REPLACE_STRERROR])
REPLACE_STRNCAT=0; AC_SUBST([REPLACE_STRNCAT])
REPLACE_STRNDUP=0; AC_SUBST([REPLACE_STRNDUP]) REPLACE_STRNDUP=0; AC_SUBST([REPLACE_STRNDUP])
REPLACE_STRSIGNAL=0; AC_SUBST([REPLACE_STRSIGNAL]) REPLACE_STRSIGNAL=0; AC_SUBST([REPLACE_STRSIGNAL])
REPLACE_STRTOK_R=0; AC_SUBST([REPLACE_STRTOK_R]) REPLACE_STRTOK_R=0; AC_SUBST([REPLACE_STRTOK_R])

106
m4/strncat.m4 Normal file
View File

@@ -0,0 +1,106 @@
# strncat.m4 serial 1
dnl Copyright (C) 2002-2004, 2009-2010 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
AC_DEFUN_ONCE([gl_FUNC_STRNCAT],
[
AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS])
AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
dnl Check for prerequisites for memory fence checks.
gl_FUNC_MMAP_ANON
AC_CHECK_HEADERS_ONCE([sys/mman.h])
AC_CHECK_FUNCS_ONCE([mprotect])
dnl Detect bug in Solaris 8..10 on SPARC:
dnl strncat should not dereference more than n bytes, but always dereferences
dnl n+1 bytes if the first n bytes don't contain a NUL byte.
dnl Assume that strncat works on platforms that lack mprotect.
AC_CACHE_CHECK([whether strncat works], [gl_cv_func_strncat_works],
[AC_RUN_IFELSE([AC_LANG_PROGRAM([[
#include <string.h>
#if HAVE_SYS_MMAN_H
# include <fcntl.h>
# include <unistd.h>
# include <sys/types.h>
# include <sys/mman.h>
# ifndef MAP_FILE
# define MAP_FILE 0
# endif
#endif
]], [[
char *fence = NULL;
#if HAVE_SYS_MMAN_H && HAVE_MPROTECT
# if HAVE_MAP_ANONYMOUS
const int flags = MAP_ANONYMOUS | MAP_PRIVATE;
const int fd = -1;
# else /* !HAVE_MAP_ANONYMOUS */
const int flags = MAP_FILE | MAP_PRIVATE;
int fd = open ("/dev/zero", O_RDONLY, 0666);
if (fd >= 0)
# endif
{
int pagesize = getpagesize ();
char *two_pages =
(char *) mmap (NULL, 2 * pagesize, PROT_READ | PROT_WRITE,
flags, fd, 0);
if (two_pages != (char *)(-1)
&& mprotect (two_pages + pagesize, pagesize, PROT_NONE) == 0)
fence = two_pages + pagesize;
}
#endif
if (fence)
{
char dest[8];
dest[0] = '*';
dest[1] = 'a';
dest[2] = '\0';
dest[3] = 'w';
dest[4] = 'x';
dest[5] = 'y';
dest[6] = 'z';
*(fence - 3) = '7';
*(fence - 2) = '2';
*(fence - 1) = '9';
if (strncat (dest + 1, fence - 3, 3) != dest + 1)
return 1;
if (dest[0] != '*')
return 2;
if (dest[1] != 'a'
|| dest[2] != '7' || dest[3] != '2' || dest[4] != '9'
|| dest[5] != '\0')
return 3;
if (dest[6] != 'z')
return 4;
}
return 0;
]])], [gl_cv_func_strncat_works=yes], [gl_cv_func_strncat_works=no],
[
case "$host_os" in
# Guess no on Solaris.
solaris*) gl_cv_func_strncat_works="guessing no";;
# Guess yes otherwise.
*) gl_cv_func_strncat_works="guessing yes";;
esac
])
])
case "$gl_cv_func_strncat_works" in
*yes) ;;
*)
REPLACE_STRNCAT=1
AC_LIBOBJ([strncat])
gl_PREREQ_STRNCAT
;;
esac
])
# Prerequisites of lib/strncat.c.
AC_DEFUN([gl_PREREQ_STRNCAT], [
:
])

View File

@@ -50,6 +50,7 @@ string.h: string.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
-e 's|@''GNULIB_STPNCPY''@|$(GNULIB_STPNCPY)|g' \ -e 's|@''GNULIB_STPNCPY''@|$(GNULIB_STPNCPY)|g' \
-e 's|@''GNULIB_STRCHRNUL''@|$(GNULIB_STRCHRNUL)|g' \ -e 's|@''GNULIB_STRCHRNUL''@|$(GNULIB_STRCHRNUL)|g' \
-e 's|@''GNULIB_STRDUP''@|$(GNULIB_STRDUP)|g' \ -e 's|@''GNULIB_STRDUP''@|$(GNULIB_STRDUP)|g' \
-e 's|@''GNULIB_STRNCAT''@|$(GNULIB_STRNCAT)|g' \
-e 's|@''GNULIB_STRNDUP''@|$(GNULIB_STRNDUP)|g' \ -e 's|@''GNULIB_STRNDUP''@|$(GNULIB_STRNDUP)|g' \
-e 's|@''GNULIB_STRNLEN''@|$(GNULIB_STRNLEN)|g' \ -e 's|@''GNULIB_STRNLEN''@|$(GNULIB_STRNLEN)|g' \
-e 's|@''GNULIB_STRPBRK''@|$(GNULIB_STRPBRK)|g' \ -e 's|@''GNULIB_STRPBRK''@|$(GNULIB_STRPBRK)|g' \
@@ -86,6 +87,7 @@ string.h: string.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
-e 's|@''REPLACE_STRDUP''@|$(REPLACE_STRDUP)|g' \ -e 's|@''REPLACE_STRDUP''@|$(REPLACE_STRDUP)|g' \
-e 's|@''REPLACE_STRSTR''@|$(REPLACE_STRSTR)|g' \ -e 's|@''REPLACE_STRSTR''@|$(REPLACE_STRSTR)|g' \
-e 's|@''REPLACE_STRERROR''@|$(REPLACE_STRERROR)|g' \ -e 's|@''REPLACE_STRERROR''@|$(REPLACE_STRERROR)|g' \
-e 's|@''REPLACE_STRNCAT''@|$(REPLACE_STRNCAT)|g' \
-e 's|@''REPLACE_STRNDUP''@|$(REPLACE_STRNDUP)|g' \ -e 's|@''REPLACE_STRNDUP''@|$(REPLACE_STRNDUP)|g' \
-e 's|@''REPLACE_STRSIGNAL''@|$(REPLACE_STRSIGNAL)|g' \ -e 's|@''REPLACE_STRSIGNAL''@|$(REPLACE_STRSIGNAL)|g' \
-e 's|@''REPLACE_STRTOK_R''@|$(REPLACE_STRTOK_R)|g' \ -e 's|@''REPLACE_STRTOK_R''@|$(REPLACE_STRTOK_R)|g' \

25
modules/strncat Normal file
View File

@@ -0,0 +1,25 @@
Description:
strncat() function: append part of a string to a string.
Files:
lib/strncat.c
m4/strncat.m4
m4/mmap-anon.m4
Depends-on:
string
configure.ac:
gl_FUNC_STRNCAT
gl_STRING_MODULE_INDICATOR([strncat])
Makefile.am:
Include:
<string.h>
License:
LGPLv2+
Maintainer:
Bruno Haible

View File

@@ -68,6 +68,11 @@ SIGNATURE_CHECK (GNULIB_NAMESPACE::strchrnul, char *, (char const *, int));
SIGNATURE_CHECK (GNULIB_NAMESPACE::strdup, char *, (char const *)); SIGNATURE_CHECK (GNULIB_NAMESPACE::strdup, char *, (char const *));
#endif #endif
#if GNULIB_TEST_STRNCAT
SIGNATURE_CHECK (GNULIB_NAMESPACE::strncat, char *,
(char *, const char *, size_t));
#endif
#if GNULIB_TEST_STRNDUP #if GNULIB_TEST_STRNDUP
SIGNATURE_CHECK (GNULIB_NAMESPACE::strndup, char *, (char const *, size_t)); SIGNATURE_CHECK (GNULIB_NAMESPACE::strndup, char *, (char const *, size_t));
#endif #endif