From d254189b38bb5b0b77a18a401c05c415ce0733c9 Mon Sep 17 00:00:00 2001 From: Jeff Johnston Date: Tue, 23 Jul 2002 21:38:00 +0000 Subject: 2002-07-23 Jeff Johnston * libc/include/string.h: Add mempcpy, strndup, and _strndup_r prototypes. * libc/stdlib/Makefile.am: Remove strdup.c and strdup_r.c. * libc/stdlib/Makefile.in: Regenerated. * libc/stdlib/strdup.c: Removed. * libc/stdlib/strdup_r.c: Removed. * libc/string/Makefile.am: Add strdup.c, strdup_r.c, memccpy.c, mempcpy.c, strndup.c, and strndup_r.c. * libc/string/Makefile.in: Regenerated. * libc/string/memccpy.c: New file. * libc/string/mempcpy.c: Ditto. * libc/string/strndup.c: Ditto. * libc/string/strndup_r.c: Ditto. * libc/string/strdup.c: New file moved from stdlib. * libc/string/strdup_r.c: Ditto. * libc/string/strings.tex: Add memccpy and mempcpy documentation. --- newlib/libc/string/Makefile.am | 9 ++- newlib/libc/string/Makefile.in | 37 +++++++---- newlib/libc/string/memccpy.c | 145 +++++++++++++++++++++++++++++++++++++++++ newlib/libc/string/mempcpy.c | 108 ++++++++++++++++++++++++++++++ newlib/libc/string/strdup.c | 13 ++++ newlib/libc/string/strdup_r.c | 17 +++++ newlib/libc/string/strings.tex | 8 +++ newlib/libc/string/strndup.c | 16 +++++ newlib/libc/string/strndup_r.c | 21 ++++++ 9 files changed, 360 insertions(+), 14 deletions(-) create mode 100644 newlib/libc/string/memccpy.c create mode 100644 newlib/libc/string/mempcpy.c create mode 100644 newlib/libc/string/strdup.c create mode 100644 newlib/libc/string/strdup_r.c create mode 100644 newlib/libc/string/strndup.c create mode 100644 newlib/libc/string/strndup_r.c (limited to 'newlib/libc/string') diff --git a/newlib/libc/string/Makefile.am b/newlib/libc/string/Makefile.am index f90fed168..525534e07 100644 --- a/newlib/libc/string/Makefile.am +++ b/newlib/libc/string/Makefile.am @@ -9,10 +9,12 @@ LIB_SOURCES = \ bcopy.c \ bzero.c \ index.c \ + memccpy.c \ memchr.c \ memcmp.c \ memcpy.c \ memmove.c \ + mempcpy.c \ memset.c \ rindex.c \ strcat.c \ @@ -22,6 +24,8 @@ LIB_SOURCES = \ strcoll.c \ strcpy.c \ strcspn.c \ + strdup.c \ + strdup_r.c \ strerror.c \ strerror_r.c \ strlcat.c \ @@ -32,6 +36,8 @@ LIB_SOURCES = \ strncmp.c \ strncasecmp.c \ strncpy.c \ + strndup.c \ + strndup_r.c \ strnlen.c \ strpbrk.c \ strrchr.c \ @@ -66,7 +72,8 @@ bzero.def memset.def strcpy.def strncpy.def strxfrm.def \ index.def rindex.def strcspn.def strpbrk.def swab.def \ 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 strlwr.def strupr.def +strcasecmp.def strncasecmp.def strlwr.def strupr.def memccpy.def \ +mempcpy.def SUFFIXES = .def diff --git a/newlib/libc/string/Makefile.in b/newlib/libc/string/Makefile.in index 32073c400..f93e20d46 100644 --- a/newlib/libc/string/Makefile.in +++ b/newlib/libc/string/Makefile.in @@ -115,10 +115,12 @@ LIB_SOURCES = \ bcopy.c \ bzero.c \ index.c \ + memccpy.c \ memchr.c \ memcmp.c \ memcpy.c \ memmove.c \ + mempcpy.c \ memset.c \ rindex.c \ strcat.c \ @@ -128,6 +130,8 @@ LIB_SOURCES = \ strcoll.c \ strcpy.c \ strcspn.c \ + strdup.c \ + strdup_r.c \ strerror.c \ strerror_r.c \ strlcat.c \ @@ -138,6 +142,8 @@ LIB_SOURCES = \ strncmp.c \ strncasecmp.c \ strncpy.c \ + strndup.c \ + strndup_r.c \ strnlen.c \ strpbrk.c \ strrchr.c \ @@ -168,7 +174,8 @@ bzero.def memset.def strcpy.def strncpy.def strxfrm.def \ index.def rindex.def strcspn.def strpbrk.def swab.def \ 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 strlwr.def strupr.def +strcasecmp.def strncasecmp.def strlwr.def strupr.def memccpy.def \ +mempcpy.def SUFFIXES = .def @@ -188,16 +195,18 @@ CPPFLAGS = @CPPFLAGS@ LIBS = @LIBS@ lib_a_LIBADD = @USE_LIBTOOL_FALSE@lib_a_OBJECTS = bcmp.$(OBJEXT) bcopy.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@bzero.$(OBJEXT) index.$(OBJEXT) memchr.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@memcmp.$(OBJEXT) memcpy.$(OBJEXT) memmove.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@memset.$(OBJEXT) rindex.$(OBJEXT) strcat.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@strchr.$(OBJEXT) strcmp.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@strcasecmp.$(OBJEXT) strcoll.$(OBJEXT) \ -@USE_LIBTOOL_FALSE@strcpy.$(OBJEXT) strcspn.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@bzero.$(OBJEXT) index.$(OBJEXT) memccpy.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@memchr.$(OBJEXT) memcmp.$(OBJEXT) memcpy.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@memmove.$(OBJEXT) mempcpy.$(OBJEXT) memset.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@rindex.$(OBJEXT) strcat.$(OBJEXT) strchr.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@strcmp.$(OBJEXT) strcasecmp.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@strcoll.$(OBJEXT) strcpy.$(OBJEXT) strcspn.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@strdup.$(OBJEXT) strdup_r.$(OBJEXT) \ @USE_LIBTOOL_FALSE@strerror.$(OBJEXT) strerror_r.$(OBJEXT) \ @USE_LIBTOOL_FALSE@strlcat.$(OBJEXT) strlcpy.$(OBJEXT) strlen.$(OBJEXT) \ @USE_LIBTOOL_FALSE@strlwr.$(OBJEXT) strncat.$(OBJEXT) strncmp.$(OBJEXT) \ @USE_LIBTOOL_FALSE@strncasecmp.$(OBJEXT) strncpy.$(OBJEXT) \ +@USE_LIBTOOL_FALSE@strndup.$(OBJEXT) strndup_r.$(OBJEXT) \ @USE_LIBTOOL_FALSE@strnlen.$(OBJEXT) strpbrk.$(OBJEXT) \ @USE_LIBTOOL_FALSE@strrchr.$(OBJEXT) strsep.$(OBJEXT) strspn.$(OBJEXT) \ @USE_LIBTOOL_FALSE@strtok.$(OBJEXT) strtok_r.$(OBJEXT) strupr.$(OBJEXT) \ @@ -207,14 +216,16 @@ LTLIBRARIES = $(noinst_LTLIBRARIES) libstring_la_LIBADD = @USE_LIBTOOL_TRUE@libstring_la_OBJECTS = bcmp.lo bcopy.lo bzero.lo \ -@USE_LIBTOOL_TRUE@index.lo memchr.lo memcmp.lo memcpy.lo memmove.lo \ -@USE_LIBTOOL_TRUE@memset.lo rindex.lo strcat.lo strchr.lo strcmp.lo \ -@USE_LIBTOOL_TRUE@strcasecmp.lo strcoll.lo strcpy.lo strcspn.lo \ +@USE_LIBTOOL_TRUE@index.lo memccpy.lo memchr.lo memcmp.lo memcpy.lo \ +@USE_LIBTOOL_TRUE@memmove.lo mempcpy.lo memset.lo rindex.lo strcat.lo \ +@USE_LIBTOOL_TRUE@strchr.lo strcmp.lo strcasecmp.lo strcoll.lo \ +@USE_LIBTOOL_TRUE@strcpy.lo strcspn.lo strdup.lo strdup_r.lo \ @USE_LIBTOOL_TRUE@strerror.lo strerror_r.lo strlcat.lo strlcpy.lo \ @USE_LIBTOOL_TRUE@strlen.lo strlwr.lo strncat.lo strncmp.lo \ -@USE_LIBTOOL_TRUE@strncasecmp.lo strncpy.lo strnlen.lo strpbrk.lo \ -@USE_LIBTOOL_TRUE@strrchr.lo strsep.lo strspn.lo strtok.lo strtok_r.lo \ -@USE_LIBTOOL_TRUE@strupr.lo strxfrm.lo strstr.lo swab.lo u_strerr.lo +@USE_LIBTOOL_TRUE@strncasecmp.lo strncpy.lo strndup.lo strndup_r.lo \ +@USE_LIBTOOL_TRUE@strnlen.lo strpbrk.lo strrchr.lo strsep.lo strspn.lo \ +@USE_LIBTOOL_TRUE@strtok.lo strtok_r.lo strupr.lo strxfrm.lo strstr.lo \ +@USE_LIBTOOL_TRUE@swab.lo u_strerr.lo CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) diff --git a/newlib/libc/string/memccpy.c b/newlib/libc/string/memccpy.c new file mode 100644 index 000000000..f677ac02e --- /dev/null +++ b/newlib/libc/string/memccpy.c @@ -0,0 +1,145 @@ +/* +FUNCTION + <>---copy memory regions with end-token check + +ANSI_SYNOPSIS + #include + void* memccpy(void *<[out]>, const void *<[in]>, + int <[endchar]>, size_t <[n]>); + +TRAD_SYNOPSIS + void *memccpy(<[out]>, <[in]>, <[endchar]>, <[n]> + void *<[out]>; + void *<[in]>; + int <[endchar]>; + size_t <[n]>; + +DESCRIPTION + This function copies up to <[n]> bytes from the memory region + pointed to by <[in]> to the memory region pointed to by + <[out]>. If a byte matching the <[endchar]> is encountered, + the byte is copied and copying stops. + + If the regions overlap, the behavior is undefined. + +RETURNS + <> returns a pointer to the first byte following the + <[endchar]> in the <[out]> region. If no byte matching + <[endchar]> was copied, then <> is returned. + +PORTABILITY +<> is a GNU extension. + +<> requires no supporting OS subroutines. + + */ + +#include <_ansi.h> +#include +#include +#include + +/* 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))) + +/* How many bytes are copied each iteration of the word copy loop. */ +#define LITTLEBLOCKSIZE (sizeof (long)) + +/* Threshhold for punting to the byte copier. */ +#define TOO_SMALL(LEN) ((LEN) < LITTLEBLOCKSIZE) + +/* Macros for detecting endchar */ +#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 + + +_PTR +_DEFUN (memccpy, (dst0, src0, endchar, len0), + _PTR dst0 _AND + _CONST _PTR src0 _AND + int endchar0 _AND + size_t len0) +{ + +#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) + _PTR ptr = NULL; + char *dst = (char *) dst0; + char *src = (char *) src0; + char endchar = endchar0 & 0xff; + + while (len0--) + { + if ((*dst++ = *src++) == endchar) + { + ptr = dst; + break; + } + } + + return ptr; +#else + _PTR ptr = NULL; + char *dst = dst0; + _CONST char *src = src0; + long *aligned_dst; + _CONST long *aligned_src; + int len = len0; + char endchar = endchar0 & 0xff; + + /* If the size is small, or either SRC or DST is unaligned, + then punt into the byte copy loop. This should be rare. */ + if (!TOO_SMALL(len) && !UNALIGNED (src, dst)) + { + int i; + unsigned long mask = 0; + + aligned_dst = (long*)dst; + aligned_src = (long*)src; + + /* The fast code reads the ASCII one word at a time and only + performs the bytewise search on word-sized segments if they + contain the search character, which is detected by XORing + the word-sized segment with a word-sized block of the search + character and then detecting for the presence of NULL in the + result. */ + for (i = 0; i < LITTLEBLOCKSIZE; i++) + mask = (mask << 8) + endchar; + + + /* Copy one long word at a time if possible. */ + while (len >= LITTLEBLOCKSIZE) + { + unsigned long buffer = (unsigned long)(*aligned_src); + buffer ^= mask; + if (DETECTNULL (buffer)) + break; /* endchar is found, go byte by byte from here */ + *aligned_dst++ = *aligned_src++; + len -= LITTLEBLOCKSIZE; + } + + /* Pick up any residual with a byte copier. */ + dst = (char*)aligned_dst; + src = (char*)aligned_src; + } + + while (len--) + { + if ((*dst++ = *src++) == endchar) + { + ptr = dst; + break; + } + } + + return ptr; +#endif /* not PREFER_SIZE_OVER_SPEED */ +} diff --git a/newlib/libc/string/mempcpy.c b/newlib/libc/string/mempcpy.c new file mode 100644 index 000000000..284cbea79 --- /dev/null +++ b/newlib/libc/string/mempcpy.c @@ -0,0 +1,108 @@ +/* +FUNCTION + <>---copy memory regions and return end pointer + +ANSI_SYNOPSIS + #include + void* mempcpy(void *<[out]>, const void *<[in]>, size_t <[n]>); + +TRAD_SYNOPSIS + void *mempcpy(<[out]>, <[in]>, <[n]> + void *<[out]>; + void *<[in]>; + size_t <[n]>; + +DESCRIPTION + This function copies <[n]> bytes from the memory region + pointed to by <[in]> to the memory region pointed to by + <[out]>. + + If the regions overlap, the behavior is undefined. + +RETURNS + <> returns a pointer to the byte following the + last byte copied to the <[out]> region. + +PORTABILITY +<> is a GNU extension. + +<> requires no supporting OS subroutines. + + */ + +#include <_ansi.h> +#include +#include +#include + +/* 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))) + +/* How many bytes are copied each iteration of the 4X unrolled loop. */ +#define BIGBLOCKSIZE (sizeof (long) << 2) + +/* How many bytes are copied each iteration of the word copy loop. */ +#define LITTLEBLOCKSIZE (sizeof (long)) + +/* Threshhold for punting to the byte copier. */ +#define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE) + +_PTR +_DEFUN (mempcpy, (dst0, src0, len0), + _PTR dst0 _AND + _CONST _PTR src0 _AND + size_t len0) +{ +#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) + char *dst = (char *) dst0; + char *src = (char *) src0; + + while (len0--) + { + *dst++ = *src++; + } + + return dst; +#else + char *dst = dst0; + _CONST char *src = src0; + long *aligned_dst; + _CONST long *aligned_src; + int len = len0; + + /* If the size is small, or either SRC or DST is unaligned, + then punt into the byte copy loop. This should be rare. */ + if (!TOO_SMALL(len) && !UNALIGNED (src, dst)) + { + aligned_dst = (long*)dst; + aligned_src = (long*)src; + + /* Copy 4X long words at a time if possible. */ + while (len >= BIGBLOCKSIZE) + { + *aligned_dst++ = *aligned_src++; + *aligned_dst++ = *aligned_src++; + *aligned_dst++ = *aligned_src++; + *aligned_dst++ = *aligned_src++; + len -= BIGBLOCKSIZE; + } + + /* Copy one long word at a time if possible. */ + while (len >= LITTLEBLOCKSIZE) + { + *aligned_dst++ = *aligned_src++; + len -= LITTLEBLOCKSIZE; + } + + /* Pick up any residual with a byte copier. */ + dst = (char*)aligned_dst; + src = (char*)aligned_src; + } + + while (len--) + *dst++ = *src++; + + return dst; +#endif /* not PREFER_SIZE_OVER_SPEED */ +} diff --git a/newlib/libc/string/strdup.c b/newlib/libc/string/strdup.c new file mode 100644 index 000000000..dbb069264 --- /dev/null +++ b/newlib/libc/string/strdup.c @@ -0,0 +1,13 @@ +#ifndef _REENT_ONLY + +#include +#include +#include + +char * +_DEFUN (strdup, (str), _CONST char *str) +{ + return _strdup_r (_REENT, str); +} + +#endif /* !_REENT_ONLY */ diff --git a/newlib/libc/string/strdup_r.c b/newlib/libc/string/strdup_r.c new file mode 100644 index 000000000..ef77a58eb --- /dev/null +++ b/newlib/libc/string/strdup_r.c @@ -0,0 +1,17 @@ +#include +#include +#include + +char * +_DEFUN (_strdup_r, (reent_ptr, str), + struct _reent *reent_ptr _AND + _CONST char *str) +{ + size_t len = strlen (str) + 1; + char *copy = _malloc_r (reent_ptr, len); + if (copy) + { + memcpy (copy, str, len); + } + return copy; +} diff --git a/newlib/libc/string/strings.tex b/newlib/libc/string/strings.tex index f70580b2c..b5435033a 100644 --- a/newlib/libc/string/strings.tex +++ b/newlib/libc/string/strings.tex @@ -10,10 +10,12 @@ managing areas of memory. The corresponding declarations are in * bcopy:: Copy memory regions * bzero:: Initialize memory to zero * index:: Search for character in string +* memccpy:: Copy memory regions up to end-token * memchr:: Find character in memory * memcmp:: Compare two memory areas * memcpy:: Copy memory regions * memmove:: Move possibly overlapping memory +* mempcpy:: Copy memory regions and locate end * memset:: Set an area of memory * rindex:: Reverse search for character in string * strcasecmp:: Compare strings ignoring case @@ -52,6 +54,9 @@ managing areas of memory. The corresponding declarations are in @page @include string/index.def +@page +@include string/memcccpy.def + @page @include string/memchr.def @@ -64,6 +69,9 @@ managing areas of memory. The corresponding declarations are in @page @include string/memmove.def +@page +@include string/mempcpy.def + @page @include string/memset.def diff --git a/newlib/libc/string/strndup.c b/newlib/libc/string/strndup.c new file mode 100644 index 000000000..caa1b68b7 --- /dev/null +++ b/newlib/libc/string/strndup.c @@ -0,0 +1,16 @@ +#ifndef _REENT_ONLY + +#include <_ansi.h> +#include +#include +#include + +char * +_DEFUN (strndup, (str, n), + _CONST char *str _AND + size_t n) +{ + return _strndup_r (_REENT, str, n); +} + +#endif /* !_REENT_ONLY */ diff --git a/newlib/libc/string/strndup_r.c b/newlib/libc/string/strndup_r.c new file mode 100644 index 000000000..86d9eec44 --- /dev/null +++ b/newlib/libc/string/strndup_r.c @@ -0,0 +1,21 @@ +#include +#include +#include + +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + +char * +_DEFUN (_strndup_r, (reent_ptr, str, n), + struct _reent *reent_ptr _AND + _CONST char *str _AND + size_t n) +{ + size_t len = MIN(strlen (str), n); + char *copy = _malloc_r (reent_ptr, len + 1); + if (copy) + { + memcpy (copy, str, len); + copy[len] = '\0'; + } + return copy; +} -- cgit v1.2.3