[patch] Add stpcpy/stpncpy

Jeff Johnston jjohnstn@redhat.com
Thu Jun 28 16:07:00 GMT 2007


Corinna,

   Please put the prototypes in the !_STRICT_ANSI_ section of string.h. 
Please put the sources in the Makefile.am ELIX_SOURCES list for now. 
Also please add the documentation references to the 
libc/string/strings.tex file.  Other than that, approved.

-- Jeff J.

Corinna Vinschen wrote:
> Hi,
> 
> the functions stpcpy and stpncpy are GNU extensions which are candidates
> for inclusion into POSIX and SUSv4.  Below is an implementation for both
> functions which I'd like to include into newlib.  They are self-written,
> basically taken from the existing strcpy/strncpy functions, to avoid
> licensing problems.  The implementation has been tested on Cygwin.
> 
> Ok to apply?
> 
> 
> Corinna
> 
> 
> 	* libc/include/string.h: Add prototypes for stpcpy and stpncpy.
> 	* libc/string/Makefile.am (GENERAL_SOURCES): Add stpcpy.c and
> 	stpncpy.c.
> 	(CHEWOUT_FILES): Add stpcpy.def and stpncpy.def.
> 	* libc/string/Makefile.in: Regenerate.
> 	* libc/string/stpcpy.c: New file.
> 	* libc/string/stpncpy.c: New file.
> 
> 
> Index: libc/include/string.h
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/include/string.h,v
> retrieving revision 1.19
> diff -u -p -r1.19 string.h
> --- libc/include/string.h	8 Jun 2007 18:38:51 -0000	1.19
> +++ libc/include/string.h	28 Jun 2007 15:12:29 -0000
> @@ -40,6 +40,9 @@ char 	*_EXFUN(strrchr,(const char *, int
>  size_t	 _EXFUN(strspn,(const char *, const char *));
>  char 	*_EXFUN(strstr,(const char *, const char *));
>  
> +char 	*_EXFUN(stpcpy,(char *, const char *));
> +char 	*_EXFUN(stpncpy,(char *, const char *, size_t));
> +
>  #ifndef _REENT_ONLY
>  char 	*_EXFUN(strtok,(char *, const char *));
>  #endif
> Index: libc/string/Makefile.am
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/string/Makefile.am,v
> retrieving revision 1.16
> diff -u -p -r1.16 Makefile.am
> --- libc/string/Makefile.am	8 Jun 2007 18:38:51 -0000	1.16
> +++ libc/string/Makefile.am	28 Jun 2007 15:12:30 -0000
> @@ -14,6 +14,8 @@ GENERAL_SOURCES = \
>  	memmove.c \
>  	memset.c \
>  	rindex.c \
> +	stpcpy.c \
> +	stpncpy.c \
>  	strcasecmp.c \
>  	strcat.c \
>  	strchr.c \
> @@ -105,7 +107,7 @@ index.def	rindex.def	strcspn.def	strpbrk
>  memchr.def	strcat.def	strerror.def	strerror_r.def strrchr.def \
>  memcmp.def	strchr.def	strlen.def	strnlen.def strspn.def \
>  strcasecmp.def	strncasecmp.def strcasestr.def	strlwr.def  strupr.def \
> -memccpy.def 	mempcpy.def \
> +memccpy.def 	mempcpy.def	stpcpy.def	stpncpy.def \
>  wcscat.def	wcschr.def	wcscmp.def	wcscoll.def \
>  wcscpy.def	wcscspn.def \
>  wcslcat.def	wcslcpy.def	wcslen.def	wcsncat.def \
> Index: libc/string/Makefile.in
> ===================================================================
> RCS file: /cvs/src/src/newlib/libc/string/Makefile.in,v
> retrieving revision 1.28
> diff -u -p -r1.28 Makefile.in
> --- libc/string/Makefile.in	8 Jun 2007 18:38:51 -0000	1.28
> +++ libc/string/Makefile.in	28 Jun 2007 15:12:30 -0000
> @@ -59,7 +59,8 @@ am__objects_1 = lib_a-bcopy.$(OBJEXT) li
>  	lib_a-index.$(OBJEXT) lib_a-memchr.$(OBJEXT) \
>  	lib_a-memcmp.$(OBJEXT) lib_a-memcpy.$(OBJEXT) \
>  	lib_a-memmove.$(OBJEXT) lib_a-memset.$(OBJEXT) \
> -	lib_a-rindex.$(OBJEXT) lib_a-strcasecmp.$(OBJEXT) \
> +	lib_a-rindex.$(OBJEXT) lib_a-stpcpy.$(OBJEXT) \
> +	lib_a-stpncpy.$(OBJEXT) lib_a-strcasecmp.$(OBJEXT) \
>  	lib_a-strcat.$(OBJEXT) lib_a-strchr.$(OBJEXT) \
>  	lib_a-strcmp.$(OBJEXT) lib_a-strcoll.$(OBJEXT) \
>  	lib_a-strcpy.$(OBJEXT) lib_a-strcspn.$(OBJEXT) \
> @@ -99,18 +100,18 @@ lib_a_OBJECTS = $(am_lib_a_OBJECTS)
>  LTLIBRARIES = $(noinst_LTLIBRARIES)
>  libstring_la_LIBADD =
>  am__objects_3 = bcopy.lo bzero.lo index.lo memchr.lo memcmp.lo \
> -	memcpy.lo memmove.lo memset.lo rindex.lo strcasecmp.lo \
> -	strcat.lo strchr.lo strcmp.lo strcoll.lo strcpy.lo strcspn.lo \
> -	strdup.lo strdup_r.lo strerror.lo strerror_r.lo strlcat.lo \
> -	strlcpy.lo strlen.lo strlwr.lo strncasecmp.lo strncat.lo \
> -	strncmp.lo strncpy.lo strnlen.lo strpbrk.lo strrchr.lo \
> -	strsep.lo strspn.lo strtok.lo strtok_r.lo strupr.lo strxfrm.lo \
> -	strstr.lo swab.lo u_strerr.lo wcscat.lo wcschr.lo wcscmp.lo \
> -	wcscoll.lo wcscpy.lo wcscspn.lo wcslcat.lo wcslcpy.lo \
> -	wcslen.lo wcsncat.lo wcsncmp.lo wcsncpy.lo wcsnlen.lo \
> -	wcspbrk.lo wcsrchr.lo wcsspn.lo wcsstr.lo wcswidth.lo \
> -	wcwidth.lo wmemchr.lo wmemcmp.lo wmemcpy.lo wmemmove.lo \
> -	wmemset.lo
> +	memcpy.lo memmove.lo memset.lo rindex.lo stpcpy.lo stpncpy.lo \
> +	strcasecmp.lo strcat.lo strchr.lo strcmp.lo strcoll.lo \
> +	strcpy.lo strcspn.lo strdup.lo strdup_r.lo strerror.lo \
> +	strerror_r.lo strlcat.lo strlcpy.lo strlen.lo strlwr.lo \
> +	strncasecmp.lo strncat.lo strncmp.lo strncpy.lo strnlen.lo \
> +	strpbrk.lo strrchr.lo strsep.lo strspn.lo strtok.lo \
> +	strtok_r.lo strupr.lo strxfrm.lo strstr.lo swab.lo u_strerr.lo \
> +	wcscat.lo wcschr.lo wcscmp.lo wcscoll.lo wcscpy.lo wcscspn.lo \
> +	wcslcat.lo wcslcpy.lo wcslen.lo wcsncat.lo wcsncmp.lo \
> +	wcsncpy.lo wcsnlen.lo wcspbrk.lo wcsrchr.lo wcsspn.lo wcsstr.lo \
> +	wcswidth.lo wcwidth.lo wmemchr.lo wmemcmp.lo wmemcpy.lo \
> +	wmemmove.lo wmemset.lo
>  @ELIX_LEVEL_1_FALSE@am__objects_4 = bcmp.lo memccpy.lo mempcpy.lo \
>  @ELIX_LEVEL_1_FALSE@	strndup.lo strcasestr.lo strndup_r.lo
>  @USE_LIBTOOL_TRUE@am_libstring_la_OBJECTS = $(am__objects_3) \
> @@ -302,6 +303,8 @@ GENERAL_SOURCES = \
>  	memmove.c \
>  	memset.c \
>  	rindex.c \
> +	stpcpy.c \
> +	stpncpy.c \
>  	strcasecmp.c \
>  	strcat.c \
>  	strchr.c \
> @@ -383,7 +386,7 @@ index.def	rindex.def	strcspn.def	strpbrk
>  memchr.def	strcat.def	strerror.def	strerror_r.def strrchr.def \
>  memcmp.def	strchr.def	strlen.def	strnlen.def strspn.def \
>  strcasecmp.def	strncasecmp.def strcasestr.def	strlwr.def  strupr.def \
> -memccpy.def 	mempcpy.def \
> +memccpy.def 	mempcpy.def	stpcpy.def	stpncpy.def \
>  wcscat.def	wcschr.def	wcscmp.def	wcscoll.def \
>  wcscpy.def	wcscspn.def \
>  wcslcat.def	wcslcpy.def	wcslen.def	wcsncat.def \
> @@ -517,6 +520,18 @@ lib_a-rindex.o: rindex.c
>  lib_a-rindex.obj: rindex.c
>  	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-rindex.obj `if test -f 'rindex.c'; then $(CYGPATH_W) 'rindex.c'; else $(CYGPATH_W) '$(srcdir)/rindex.c'; fi`
>  
> +lib_a-stpcpy.o: stpcpy.c
> +	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-stpcpy.o `test -f 'stpcpy.c' || echo '$(srcdir)/'`stpcpy.c
> +
> +lib_a-stpcpy.obj: stpcpy.c
> +	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-stpcpy.obj `if test -f 'stpcpy.c'; then $(CYGPATH_W) 'stpcpy.c'; else $(CYGPATH_W) '$(srcdir)/stpcpy.c'; fi`
> +
> +lib_a-stpncpy.o: stpncpy.c
> +	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-stpncpy.o `test -f 'stpncpy.c' || echo '$(srcdir)/'`stpncpy.c
> +
> +lib_a-stpncpy.obj: stpncpy.c
> +	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-stpncpy.obj `if test -f 'stpncpy.c'; then $(CYGPATH_W) 'stpncpy.c'; else $(CYGPATH_W) '$(srcdir)/stpncpy.c'; fi`
> +
>  lib_a-strcasecmp.o: strcasecmp.c
>  	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strcasecmp.o `test -f 'strcasecmp.c' || echo '$(srcdir)/'`strcasecmp.c
>  
> Index: libc/string/stpcpy.c
> ===================================================================
> RCS file: libc/string/stpcpy.c
> diff -N libc/string/stpcpy.c
> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ libc/string/stpcpy.c	28 Jun 2007 15:12:30 -0000
> @@ -0,0 +1,91 @@
> +/*
> +FUNCTION
> +	<<stpcpy>>---copy string returning a pointer to its end
> +
> +INDEX
> +	stpcpy
> +
> +ANSI_SYNOPSIS
> +	#include <string.h>
> +	char *stpcpy(char *<[dst]>, const char *<[src]>);
> +
> +TRAD_SYNOPSIS
> +	#include <string.h>
> +	char *stpcpy(<[dst]>, <[src]>)
> +	char *<[dst]>;
> +	char *<[src]>;
> +
> +DESCRIPTION
> +	<<stpcpy>> copies the string pointed to by <[src]>
> +	(including the terminating null character) to the array
> +	pointed to by <[dst]>.
> +
> +RETURNS
> +	This function returns a pointer to the end of the destination string,
> +	thus pointing to the trailing '\0'.
> +
> +PORTABILITY
> +<<stpcpy>> is a GNU extension, candidate for inclusion into POSIX/SUSv4.
> +
> +<<stpcpy>> requires no supporting OS subroutines.
> +
> +QUICKREF
> +	stpcpy gnu
> +*/
> +
> +#include <string.h>
> +#include <limits.h>
> +
> +/*SUPPRESS 560*/
> +/*SUPPRESS 530*/
> +
> +/* Nonzero if either X or Y is not aligned on a "long" boundary.  */
> +#define UNALIGNED(X, Y) \
> +  (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
> +
> +#if LONG_MAX == 2147483647L
> +#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
> +#else
> +#if LONG_MAX == 9223372036854775807L
> +/* Nonzero if X (a long int) contains a NULL byte. */
> +#define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080)
> +#else
> +#error long int is not a 32bit or 64bit type.
> +#endif
> +#endif
> +
> +#ifndef DETECTNULL
> +#error long int is not a 32bit or 64bit byte
> +#endif
> +
> +char*
> +_DEFUN (stpcpy, (dst, src),
> +	char *dst _AND
> +	_CONST char *src)
> +{
> +#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
> +  long *aligned_dst;
> +  _CONST long *aligned_src;
> +
> +  /* If SRC or DEST is unaligned, then copy bytes.  */
> +  if (!UNALIGNED (src, dst))
> +    {
> +      aligned_dst = (long*)dst;
> +      aligned_src = (long*)src;
> +
> +      /* SRC and DEST are both "long int" aligned, try to do "long int"
> +         sized copies.  */
> +      while (!DETECTNULL(*aligned_src))
> +        {
> +          *aligned_dst++ = *aligned_src++;
> +        }
> +
> +      dst = (char*)aligned_dst;
> +      src = (char*)aligned_src;
> +    }
> +#endif /* not PREFER_SIZE_OVER_SPEED */
> +
> +  while ((*dst++ = *src++))
> +    ;
> +  return --dst;
> +}
> Index: libc/string/stpncpy.c
> ===================================================================
> RCS file: libc/string/stpncpy.c
> diff -N libc/string/stpncpy.c
> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ libc/string/stpncpy.c	28 Jun 2007 15:12:30 -0000
> @@ -0,0 +1,114 @@
> +/*
> +FUNCTION
> +	<<stpncpy>>---counted copy string returning a pointer to its end
> +
> +INDEX
> +	stpncpy
> +
> +ANSI_SYNOPSIS
> +	#include <string.h>
> +	char *stpncpy(char *<[dst]>, const char *<[src]>, size_t <[length]>);
> +
> +TRAD_SYNOPSIS
> +	#include <string.h>
> +	char *stpncpy(<[dst]>, <[src]>, <[length]>)
> +	char *<[dst]>;
> +	char *<[src]>;
> +	size_t <[length]>;
> +
> +DESCRIPTION
> +	<<stpncpy>> copies not more than <[length]> characters from the
> +	the string pointed to by <[src]> (including the terminating
> +	null character) to the array pointed to by <[dst]>.  If the
> +	string pointed to by <[src]> is shorter than <[length]>
> +	characters, null characters are appended to the destination
> +	array until a total of <[length]> characters have been
> +	written.
> +
> +RETURNS
> +	This function returns a pointer to the end of the destination string,
> +	thus pointing to the trailing '\0', or, if the destination string is
> +	not null-terminated, pointing to dst + n.
> +
> +PORTABILITY
> +<<stpncpy>> is a GNU extension, candidate for inclusion into POSIX/SUSv4.
> +
> +<<stpncpy>> requires no supporting OS subroutines.
> +
> +QUICKREF
> +	stpncpy gnu
> +*/
> +
> +#include <string.h>
> +#include <limits.h>
> +
> +/*SUPPRESS 560*/
> +/*SUPPRESS 530*/
> +
> +/* Nonzero if either X or Y is not aligned on a "long" boundary.  */
> +#define UNALIGNED(X, Y) \
> +  (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
> +
> +#if LONG_MAX == 2147483647L
> +#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
> +#else
> +#if LONG_MAX == 9223372036854775807L
> +/* Nonzero if X (a long int) contains a NULL byte. */
> +#define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080)
> +#else
> +#error long int is not a 32bit or 64bit type.
> +#endif
> +#endif
> +
> +#ifndef DETECTNULL
> +#error long int is not a 32bit or 64bit byte
> +#endif
> +
> +#define TOO_SMALL(LEN) ((LEN) < sizeof (long))
> +
> +char *
> +_DEFUN (stpncpy, (dst, src),
> +	char *dst _AND
> +	_CONST char *src _AND
> +	size_t count)
> +{
> +  char *ret = NULL;
> +
> +#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
> +  long *aligned_dst;
> +  _CONST long *aligned_src;
> +
> +  /* If SRC and DEST is aligned and count large enough, then copy words.  */
> +  if (!UNALIGNED (src, dst) && !TOO_SMALL (count))
> +    {
> +      aligned_dst = (long*)dst;
> +      aligned_src = (long*)src;
> +
> +      /* SRC and DEST are both "long int" aligned, try to do "long int"
> +	 sized copies.  */
> +      while (count >= sizeof (long int) && !DETECTNULL(*aligned_src))
> +	{
> +	  count -= sizeof (long int);
> +	  *aligned_dst++ = *aligned_src++;
> +	}
> +
> +      dst = (char*)aligned_dst;
> +      src = (char*)aligned_src;
> +    }
> +#endif /* not PREFER_SIZE_OVER_SPEED */
> +
> +  while (count > 0)
> +    {
> +      --count;
> +      if ((*dst++ = *src++) == '\0')
> +	{
> +	  ret = dst - 1;
> +	  break;
> +	}
> +    }
> +
> +  while (count-- > 0)
> +    *dst++ = '\0';
> +
> +  return ret ? ret : dst;
> +}
> 



More information about the Newlib mailing list