This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] Add stpcpy/stpncpy


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;
+}

-- 
Corinna Vinschen
Cygwin Project Co-Leader
Red Hat


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]