X-Authentication-Warning: delorie.com: mail set sender to djgpp-workers-bounces using -f X-Recipient: djgpp-workers AT delorie DOT com Message-ID: <5285335D.8020407@gmx.de> Date: Thu, 14 Nov 2013 21:32:29 +0100 From: Juan Manuel Guerrero User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:16.0) Gecko/20121025 Thunderbird/16.0.2 MIME-Version: 1.0 To: djgpp-workers AT delorie DOT com Subject: Re: Implementations for strndup and strnlen. References: <527D6EA1 DOT 6030506 AT gmx DOT de> In-Reply-To: <527D6EA1.6030506@gmx.de> Content-Type: text/plain; charset=ISO-8859-15; format=flowed Content-Transfer-Encoding: 7bit X-Provags-ID: V03:K0:ooAhUP/qEQvMSMyBvlnq1w2aSzXtOiStCuevTrFhP0TpnWXMoA5 kBvfukoTenm69mrwDXAVxYYfgJpGf1/U23Qgk6EHeuJDPoQ0eU+xQrA8uFNGyF2UvshfMzY u4lV+wtWHD45/48Cqc+jCnraYPKCmTfioaRUGgTKZxIZpC1gGWXzUUnjRZavljxRJMc6tB2 HYY5QFdo24BFTfs7+60Tg== Reply-To: djgpp-workers AT delorie DOT com Am 09.11.2013 00:07, schrieb Juan Manuel Guerrero: > The patch below provides implementations for strndup and strnlen together with > some small test cases. > OFYI: I have committed the patch below. Regards, Juan M. Guerrero 2013-11-07 Juan Manuel Guerrero * djgpp/include/string.h: Added declarations for strndup and strnlen. * djgpp/src/libc/posix/string/makefile: strndup and strnlen added to goal list. * djgpp/src/libc/compat/string/strndup.c: Implementation of strndup. * djgpp/src/libc/compat/string/strndup.txh: Documentation of strndup. * djgpp/src/libc/compat/string/strnlen.c: Implementation of strnlen. * djgpp/src/libc/compat/string/strnlen.txh: Documentation of strnlen. * djgpp/src/docs/kb/wc204.txi: Info about strndup and strnlen added. * djgpp/tests/libc/posix/string/makefile: strndup and strnlen checks added to goal list. * djgpp/tests/libc/posix/string/strndup.c: Check for strndup. * djgpp/tests/libc/posix/string/strnlen.c: Check for strnlen. diff -aprNU5 djgpp.orig/include/string.h djgpp/include/string.h --- djgpp.orig/include/string.h 2012-09-23 07:49:12 +0100 +++ djgpp/include/string.h 2013-11-08 23:06:52 +0100 @@ -69,23 +69,25 @@ char * strtok_r(char * _s1, const char int bcmp(const void *_ptr1, const void *_ptr2, int _length); void bcopy(const void *_a, void *_b, size_t _len); void bzero(void *ptr, size_t _len); int ffs(int _mask); char * index(const char *_string, int _c); -void * memccpy(void *_to, const void *_from, int c, size_t n); +void * memccpy(void *_to, const void *_from, int _c, size_t _n); int memicmp(const void *_s1, const void *_s2, size_t _n); char * rindex(const char *_string, int _c); char * stpcpy(char *_dest, const char *_src); char * stpncpy(char *_dest, const char *_src, size_t _n); char * strdup(const char *_s); +char * strndup(const char *_s, size_t _n); size_t strlcat(char *_dest, const char *_src, size_t _size); size_t strlcpy(char *_dest, const char *_src, size_t _size); char * strlwr(char *_s); int strcasecmp(const char *_s1, const char *_s2); int stricmp(const char *_s1, const char *_s2); int strncasecmp(const char *_s1, const char *_s2, size_t _n); int strnicmp(const char *_s1, const char *_s2, size_t _n); +size_t strnlen(const char *_s, size_t _n); char * strsep(char **_stringp, const char *_delim); char * strupr(char *_s); #endif /* !_POSIX_SOURCE */ #endif /* !__STRICT_ANSI__ */ diff -aprNU5 djgpp.orig/src/docs/kb/wc204.txi djgpp/src/docs/kb/wc204.txi --- djgpp.orig/src/docs/kb/wc204.txi 2013-11-08 23:05:16 +0100 +++ djgpp/src/docs/kb/wc204.txi 2013-11-08 23:33:56 +0100 @@ -1342,5 +1342,11 @@ The @acronym{C99} functions @code{lround These functions are available in two versions. @cindex @acronym{C99} compliance, @code{math.h} @findex rintl AT r{ added} The @acronym{C99} function @code{rintl} has been added to comply with the @acronym{C99} standard. + +@cindex @acronym{POSIX} compliance, @code{string.h} +@findex strndup AT r{ added} +@findex strnlen AT r{ added} +The functions @code{strndup} and @code{strnlen} were added to comply with +the @acronym{POSIX} 1003.1-2008 standard. diff -aprNU5 djgpp.orig/src/libc/posix/string/makefile djgpp/src/libc/posix/string/makefile --- djgpp.orig/src/libc/posix/string/makefile 2005-01-07 17:07:16 +0100 +++ djgpp/src/libc/posix/string/makefile 2013-11-08 23:06:52 +0100 @@ -1,7 +1,10 @@ +# Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details # Copyright (C) 2005 DJ Delorie, see COPYING.DJ for details TOP=../.. SRC += strtok_r.c SRC += strerr_r.c +SRC += strndup.c +SRC += strnlen.c include $(TOP)/../makefile.inc diff -aprNU5 djgpp.orig/src/libc/posix/string/strndup.c djgpp/src/libc/posix/string/strndup.c --- djgpp.orig/src/libc/posix/string/strndup.c 1970-01-01 01:00:00 +0100 +++ djgpp/src/libc/posix/string/strndup.c 2013-11-08 23:06:52 +0100 @@ -0,0 +1,24 @@ +/* Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +char * +strndup(const char *_s, size_t _n) +{ + if (_s == NULL) + return NULL; + else + { + register const size_t length = strlen(_s); + register const size_t bytes = length > _n ? _n : length; + register char *new_string = malloc(bytes + 1); + + if (new_string) + { + memcpy(new_string, _s, bytes); + new_string[bytes] = '\0'; + } + + return new_string; + } +} diff -aprNU5 djgpp.orig/src/libc/posix/string/strndup.txh djgpp/src/libc/posix/string/strndup.txh --- djgpp.orig/src/libc/posix/string/strndup.txh 1970-01-01 01:00:00 +0100 +++ djgpp/src/libc/posix/string/strndup.txh 2013-11-08 23:06:52 +0100 @@ -0,0 +1,34 @@ +@node strndup, string +@findex strndup +@subheading Syntax + +@example +#include + +char * strndup (const char *source, size_t size); +@end example + +@subheading Description + +Returns a newly allocated area of memory that contains a duplicate of at most +@var{size} of characters of the string pointed to by @var{source}. The memory +returned by this call must be freed by the caller. + +@subheading Return Value + +Returns the newly allocated string, or @var{NULL} if there +is no more memory. + +@subheading Portability + +@portability !ansi, posix-1003.1-2008 + +@subheading Example + +@example +char *foo() +@{ + return strndup("hello world", 5); +@} +@end example + diff -aprNU5 djgpp.orig/src/libc/posix/string/strnlen.c djgpp/src/libc/posix/string/strnlen.c --- djgpp.orig/src/libc/posix/string/strnlen.c 1970-01-01 01:00:00 +0100 +++ djgpp/src/libc/posix/string/strnlen.c 2013-11-08 23:06:52 +0100 @@ -0,0 +1,19 @@ +/* Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details */ +#include + +size_t +strnlen(const char *_str, size_t _n) +{ + if (_str == NULL || *_str == '\0' || _n == 0) + return 0; + else + { + register size_t i; + + for (i = 1; _str[i] && i < _n; i++) + ; + + return i; + } +} + diff -aprNU5 djgpp.orig/src/libc/posix/string/strnlen.txh djgpp/src/libc/posix/string/strnlen.txh --- djgpp.orig/src/libc/posix/string/strnlen.txh 1970-01-01 01:00:00 +0100 +++ djgpp/src/libc/posix/string/strnlen.txh 2013-11-08 23:21:30 +0100 @@ -0,0 +1,34 @@ +@node strnlen, string +@findex strnlen +@subheading Syntax + +@example +#include + +size_t strnlen(const char *string, size_t size); +@end example + +@subheading Description + +This function returns the number of characters in @var{string}, +but at most @var{size}. In doing this, the function looks only +at the first @var{size} characters at @var{string} and never +beyond @var{string} + @var{size}. + +@subheading Return Value + +The length of the string. + +@subheading Portability + +@portability !ansi, posix-1003.1-2008 + +@subheading Example + +@example +size_t max_string_length = 10000; + +if (strnlen(fname, max_string_length) > PATH_MAX) + invalid_file(fname); +@end example + diff -aprNU5 djgpp.orig/tests/libc/posix/string/makefile djgpp/tests/libc/posix/string/makefile --- djgpp.orig/tests/libc/posix/string/makefile 2005-01-07 17:07:16 +0100 +++ djgpp/tests/libc/posix/string/makefile 2013-11-08 23:06:52 +0100 @@ -1,5 +1,7 @@ TOP=../.. SRC += strerr_r.c +SRC += strndup.c +SRC += strnlen.c include $(TOP)/../makefile.inc diff -aprNU5 djgpp.orig/tests/libc/posix/string/strndup.c djgpp/tests/libc/posix/string/strndup.c --- djgpp.orig/tests/libc/posix/string/strndup.c 1970-01-01 01:00:00 +0100 +++ djgpp/tests/libc/posix/string/strndup.c 2013-11-08 23:06:52 +0100 @@ -0,0 +1,94 @@ +#include +#include +#include + +#define SOURCE "A string to duplicate." + + +int main(void) +{ + char *psrc, src[] = SOURCE; + char *dst[10]; + int rv = 0; + register int i; + + + dst[0] = strndup(src, sizeof(SOURCE)); + if (!dst[0]) + rv++; + else + { + for (i = 0; dst[0][i] == src[i]; i++) + ; + if (i != sizeof(SOURCE)) + rv++; + } + + dst[1] = strndup(src, sizeof(SOURCE) + 1); + if (!dst[1]) + rv++; + else + { + for (i = 0; dst[1][i] == src[i]; i++) + ; + if (i != sizeof(SOURCE)) + rv++; + } + + dst[2] = strndup(src, sizeof(SOURCE) - 1); + if (!dst[2]) + rv++; + else + { + for (i = 0; dst[2][i] == src[i]; i++) + ; + if (i != sizeof(SOURCE)) + rv++; + } + + dst[3] = strndup(src, sizeof(SOURCE) - 2); + if (!dst[3]) + rv++; + else + { + for (i = 0; dst[3][i] == src[i]; i++) + ; + if (i != sizeof(SOURCE) - 2) + rv++; + } + + dst[4] = strndup(src, 0); + if (!dst[4]) + rv++; + else + { + for (i = 0; dst[4][i] == src[i]; i++) + ; + if (i != 0) + rv++; + } + + src[0] = '\0'; + dst[5] = strndup(src, 1000); + if (!dst[5]) + rv++; + else + { + for (i = 0; dst[5][i] == src[i]; i++) + ; + if (i != 1) + rv++; + } + + psrc = NULL; + dst[6] = strndup(psrc, 1000); + if (dst[6]) + rv++; + + for (i = 0; dst[i]; i++) + free(dst[i]); + + + printf("%d checks of strndup failed.\n", rv); + return rv; +} diff -aprNU5 djgpp.orig/tests/libc/posix/string/strnlen.c djgpp/tests/libc/posix/string/strnlen.c --- djgpp.orig/tests/libc/posix/string/strnlen.c 1970-01-01 01:00:00 +0100 +++ djgpp/tests/libc/posix/string/strnlen.c 2013-11-08 23:06:52 +0100 @@ -0,0 +1,38 @@ +#include +#include +#include + +#define SOURCE "A string to check." + + +int main(void) +{ + char *psrc = NULL, src[] = SOURCE; + int rv = 0; + + + if (strnlen(src, sizeof(SOURCE) + 1000) != sizeof(SOURCE) - 1) + rv++; + + if (strnlen(src, sizeof(SOURCE)) != sizeof(SOURCE) - 1) + rv++; + + if (strnlen(src, sizeof(SOURCE) - 1) != sizeof(SOURCE) - 1) + rv++; + + if (strnlen(src, sizeof(SOURCE) - 2) != sizeof(SOURCE) - 2) + rv++; + + if (strnlen(src, 0) != 0) + rv++; + + if (strnlen(psrc, sizeof(SOURCE) + 1000) != 0) + rv++; + + src[sizeof(SOURCE) - 1] = 'z'; + if (strnlen(src, sizeof(SOURCE) + 10) > sizeof(SOURCE) + 10) + rv++; + + printf("%d checks of strnlen failed.\n", rv); + return rv; +}