delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2013/11/08/18:05:40

X-Authentication-Warning: delorie.com: mail set sender to djgpp-workers-bounces using -f
X-Recipient: djgpp-workers AT delorie DOT com
Message-ID: <527D6EA1.6030506@gmx.de>
Date: Sat, 09 Nov 2013 00:07:13 +0100
From: Juan Manuel Guerrero <juan DOT guerrero AT gmx DOT de>
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: Implementations for strndup and strnlen.
X-Provags-ID: V03:K0:v+5fncifPcfbJo5Gi6MP6hIdom787cI0VuLafQHdXoFRCq3S8DR
bjDgdglIBFANmQB1RHWlVxqsgJIVWPqyEpH4jZK1BvJW2LEm+i1cvLCIT+6MKuPDIz7zUTi
nfKmBMpDzXU6ttBh9Kg4RnnxIM0Glappwt0ul/vtMmfmMPU3ohJG0PFW7Uy5LBwWHTUIZTJ
/R5x/VJBbdrk+bhRWoH2A==
Reply-To: djgpp-workers AT delorie DOT com

The patch below provides implementations for strndup and strnlen together with
some small test cases.

Regards,
Juan M. Guerrero



2013-11-07  Juan Manuel Guerrero  <juan DOT guerrero AT gmx DOT de>


     * 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 <string.h>
+#include <stdlib.h>
+
+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 *rv = malloc(bytes + 1);
+
+    if (rv)
+    {
+      memcpy(rv, _s, bytes);
+      rv[bytes] = '\0';
+    }
+
+    return rv;
+  }
+}
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 <string.h>
+
+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 <string.h>
+
+size_t
+strnlen(const char *_str, size_t _n)
+{
+  if (_str == NULL || _n == 0 || *_str == '\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 <string.h>
+
+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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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;
+}

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019