This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
[patch] Add stpcpy/stpncpy
- From: Corinna Vinschen <vinschen at redhat dot com>
- To: newlib at sourceware dot org
- Date: Thu, 28 Jun 2007 17:15:27 +0200
- Subject: [patch] Add stpcpy/stpncpy
- Reply-to: newlib at sourceware dot org
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