Alain wrote:


Arkady V.Belousov escreveu:

A> BTW: do you have information about memcpy() problems in BC 3.1 ? Last

     My BC bugs list contains:

- Result of intrinsic-version of "memcmp" function undefined when third
  argument is zero.
  FIX: check size of compared memory blocks before "memcmp".

Probably, memcpy() contains same bug. Which one you mean?


I mean mamcpy(), but I will check it it could possibly have the 3rd argument =0. thanks.

Alain

Wouldn't that be a library and not a compiler problem? ;-)

Here's my free implementation of all the mem* functions. You can use it for comparison:

/* bcmp, bcopy, bzero, memccpy, memchr, memcmp, memcpy, memmove, memset
  -- memory-manipulation functions

 AUTHOR: Gregory Pietsch

 NAME

   bcmp - memory operations (LEGACY)
   bcopy - memory operations (LEGACY)
   bzero - memory operations (LEGACY)
   memccpy - copy bytes in memory
   memchr - find byte in memory
   memcmp - compare bytes in memory
   memcpy - copy bytes in memory
   memmove - copy bytes in memory with overlapping areas
   memset - set bytes in memory

 SYNOPSIS

   #include <strings.h>

   int bcmp(const void *s1, const void *s2, size_t n);
   void bcopy(const void *s2, void *s1, size_t n);
   void bzero(void *s, size_t n);

   #include <string.h>

   void *memccpy(void *restrict s1, const void *restrict s2, int c,
               size_t n);
   void *memchr(const void *s, int c, size_t n);
   int memcmp(const void *s1, const void *s2, size_t n);
   void *memcpy(void * restrict s1, const void * restrict s2, size_t n);
   void *memmove(void *s1, const void *s2, size_t n);
   void *memset(void *s, int c, size_t n);

 DESCRIPTION

The functionality described on this reference page is aligned with the
ISO C standard. Any conflict between the requirements described here and
the ISO C standard is unintentional. This volume of IEEE Std 1003.1-2001
defers to the ISO C standard.


   The bcmp() function shall compare the first n bytes of the area pointed
   to by s1 with the area pointed to by s2.

The bcopy() function shall copy n bytes from the area pointed to by s1 to
the area pointed to by s2. The bytes are copied correctly even if the
area pointed to by s1 overlaps the area pointed to by s2.


The bzero() function shall place n zero-valued bytes in the area pointed
to by s.


   The memccpy() function shall copy bytes from memory area s2 into s1,
   stopping after the first occurrence of byte c (converted to an unsigned
   char) is copied, or after n bytes are copied, whichever comes first. If
   copying takes place between objects that overlap, the behavior is
   undefined.

The memchr() function shall locate the first occurrence of c (converted
to an unsigned char) in the initial n bytes (each interpreted as unsigned
char) of the object pointed to by s.


The memcmp() function shall compare the first n bytes (each interpreted
as unsigned char) of the object pointed to by s1 to the first n bytes of
the object pointed to by s2. The sign of a non-zero return value shall
be determined by the sign of the difference between the values of the
first pair of bytes (both interpreted as type unsigned char) that differ
in the objects being compared.


   The memcpy() function shall copy n bytes from the object pointed to by
   s2 into the object pointed to by s1. If copying takes place between
   objects that overlap, the behavior is undefined.

The memmove() function shall copy n bytes from the object pointed to by
s2 into the object pointed to by s1. Copying takes place as if the n
bytes from the object pointed to by s2 are first copied into a temporary
array of n bytes that does not overlap the objects pointed to by s1 and
s2, and then the n bytes from the temporary array are copied into the
object pointed to by s1.


   The memset() function shall copy c (converted to an unsigned char) into
   each of the first n bytes of the object pointed to by s.

 RETURN VALUE

The bcmp() function shall return 0 if s1 and s2 are identical; otherwise,
it shall return non-zero. Both areas are assumed to be n bytes long. If
the value of n is 0, bcmp() shall return 0.


The bcopy() and bzero() functions shall not return a value.
The memccpy() function shall return a pointer to the byte after the copy
of c in s1, or a null pointer if c was not found in the first n bytes of
s2.


   The memchr() function shall return a pointer to the located byte, or a
   null pointer if the byte does not occur in the object.

The memcmp() function shall return an integer greater than, equal to, or
less than 0, if the object pointed to by s1 is greater than, equal to,
or less than the object pointed to by s2, respectively.


   The memcpy() function shall return s1; no return value is reserved to
   indicate an error.

   The memmove() function shall return s1; no return value is reserved to
   indicate an error.

   The memset() function shall return s; no return value is reserved to
   indicate an error.

 ERRORS

   No errors are defined.

 NOTES

   These macros, if set on the compile line, modify the behavior of these
   functions.

   _ALIGN - defined if unsigned longs need to be on an unsigned long
   boundary in memory. This is not true on PCs, but is true on some
   mainframes.

   _OPTIMIZED_FOR_SIZE - defined if the special code to scan or copy
   an unsigned long at a time needs to be cast out.
*/

#include <string.h>
#include <strings.h>

#ifndef _OPTIMIZED_FOR_SIZE

#include <limits.h>

/* Nonzero if either X or Y is not aligned on a "long" boundary. */
#ifdef _ALIGN
#define UNALIGNED1(X) ((long)X&(sizeof(long)-1))
#define UNALIGNED2(X,Y) (((long)X&(sizeof(long)-1))|((long)Y&(sizeof(long)-1)))
#else
#define UNALIGNED1(X) 0
#define UNALIGNED2(X,Y) 0
#endif


/* How many bytes are copied each iteration of the word copy loop.  */
#define BLOCKSIZE (sizeof (long))

/* Threshhold for punting to the byte copier.  */
#define TOO_SMALL(LEN)  ((LEN) < BLOCKSIZE)

/* Macros for detecting endchar */
#if ULONG_MAX == 0xFFFFFFFFUL
#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
#elif ULONG_MAX == 0xFFFFFFFFFFFFFFFFUL
/* Nonzero if X (a long int) contains a NULL byte. */
#define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080)
#else
#define _OPTIMIZED_FOR_SIZE
#endif


#endif

/* bcmp */
int (bcmp)(const void *s1, const void *s2, size_t n)
{
   return memcmp(s1, s2, n);
}

/* bcopy */
void (bcopy)(const void *s1, void *s2, size_t n)
{
   memmove(s2, s1, n);
}

/* bzero */
void (bzero)(void *s, size_t n)
{
   memset(s, '\0', n);
}

/* memccpy */
void *(memccpy)(void *restrict s1, const void *restrict s2, int c, size_t n)
{
   unsigned char *us1 = s1, uc = c;
   const unsigned char *us2 = s2;
   void *s = 0;
#ifndef _OPTIMIZED_FOR_SIZE
   unsigned long *ul1, *ul2, mask, buffer;
   size_t i;

   /* 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(n) && !UNALIGNED2(s1, s2)) {
       for (mask = uc, i = 1; i < sizeof(unsigned long);
            mask += (mask << (i * CHAR_BIT)), i << 1);
       /* 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.  */
       ul1 = (unsigned long *) us1;
       ul2 = (unsigned long *) us2;
       /* Copy one long word at a time if possible.  */
       while (n >= BLOCKSIZE) {
           buffer = *us2 ^ mask;
           if (DETECTNULL(buffer))
               break;          /* uc is found, go byte by byte from here */
           *ul1++ = *ul2++;
           n -= BLOCKSIZE;
       }
       us1 = (unsigned char *) ul1;
       us2 = (unsigned char *) ul2;
   }
#endif
   while (n--) {
       if ((*us1++ = *us2++) == uc) {
           s = (void *) us1;
           break;
       }
   }
   return s;
}

/* memchr */
void *(memchr)(const void *s, int c, size_t n)
{
   const unsigned char *src = s;
   unsigned char uc = c;
#ifndef _OPTIMIZED_FOR_SIZE
   unsigned long *asrc, buffer, mask;
   size_t i;

   /* If the size is small, or src is unaligned, then
      use the bytewise loop.  We can hope this is rare.  */
   if (!TOO_SMALL(n) && !UNALIGNED1(s)) {
       for (mask = uc, i = 1; i < sizeof(unsigned long);
            mask += (mask << (i * CHAR_BIT)), i << 1);
       /* 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.  */
       asrc = (unsigned long *) src;
       while (n >= BLOCKSIZE) {
           buffer = *asrc ^ mask;
           if (DETECTNULL(buffer))
               break;
           n -= BLOCKSIZE;
           asrc++;
       }
       /* If there are fewer than BLOCKSIZE characters left,
          then we resort to the bytewise loop.  */
       src = (unsigned char *) asrc;
   }
#endif
   while (n--) {
       if (*src == uc)
           return (void *) src;
       src++;
   }
   return 0;
}

/* memcmp */
int (memcmp)(const void *s1, const void *s2, size_t n)
{
   unsigned char *us1 = (unsigned char *) s1;
   unsigned char *us2 = (unsigned char *) s2;
#ifndef _OPTIMIZED_FOR_SIZE
   unsigned long *a1;
   unsigned long *a2;

   /* If the size is too small, or either pointer is unaligned,
      then we punt to the byte compare loop.  Hopefully this will
      not turn up in inner loops.  */
   if (!TOO_SMALL(n) && !UNALIGNED2(s1, s2)) {
       /* Otherwise, load and compare the blocks of memory one
          word at a time.  */
       a1 = (unsigned long *) us1;
       a2 = (unsigned long *) us2;
       while (n >= BLOCKSIZE) {
           if (*a1 != *a2)
               break;
           a1++;
           a2++;
           n -= BLOCKSIZE;
       }
       /* check remaining characters */
       us1 = (char *) a1;
       us2 = (char *) a2;
   }
#endif
   while (n--) {
       if (*us1 != *us2)
           return (*us1 < *us2) ? -1 : +1;
       us1++;
       us2++;
   }
   return 0;
}

/* memcpy */
void *(memcpy)(void *restrict s1, const void *restrict s2, size_t n)
{
   char *dst = s1;
   const char *src = s2;
#ifndef _OPTIMIZED_FOR_SIZE
   long *aligned_dst;
   const long *aligned_src;

/* Use optimizing algorithm for a non-destructive copy. 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(n) && !UNALIGNED2(src, dst)) {
aligned_dst = (long *) dst;
aligned_src = (long *) src;
/* Copy 4X long words at a time if possible. */
while (n >= 4 * BLOCKSIZE) {
*aligned_dst++ = *aligned_src++;
*aligned_dst++ = *aligned_src++;
*aligned_dst++ = *aligned_src++;
*aligned_dst++ = *aligned_src++;
n -= 4 * BLOCKSIZE;
}
/* Copy one long word at a time if possible. */
while (n >= BLOCKSIZE) {
*aligned_dst++ = *aligned_src++;
n -= BLOCKSIZE;
}
/* Pick up any residual with a byte copier. */
dst = (char *) aligned_dst;
src = (char *) aligned_src;
}
#endif
while (n--)
*dst++ = *src++;
return s1;
}


/* memmove */
void *(memmove)(void *s1, const void *s2, size_t n)
{
   char *dst = s1;
   const char *src = s2;
#ifndef _OPTIMIZED_FOR_SIZE
   long *aligned_dst;
   const long *aligned_src;
#endif

if (src < dst && dst < src + n) {
/* Destructive overlap...have to copy backwards */
src += n;
dst += n;
while (n--)
*--dst = *--src;
} else {
#ifndef _OPTIMIZED_FOR_SIZE
/* Use optimizing algorithm for a non-destructive copy to closely
match memcpy. 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(n) && !UNALIGNED2(src, dst)) {
aligned_dst = (long *) dst;
aligned_src = (long *) src;
/* Copy 4X long words at a time if possible. */
while (n >= 4 * BLOCKSIZE) {
*aligned_dst++ = *aligned_src++;
*aligned_dst++ = *aligned_src++;
*aligned_dst++ = *aligned_src++;
*aligned_dst++ = *aligned_src++;
n -= 4 * BLOCKSIZE;
}
/* Copy one long word at a time if possible. */
while (n >= BLOCKSIZE) {
*aligned_dst++ = *aligned_src++;
n -= BLOCKSIZE;
}
/* Pick up any residual with a byte copier. */
dst = (char *) aligned_dst;
src = (char *) aligned_src;
}
#endif
while (n--)
*dst++ = *src++;
}
return s1;
}


/* memset */
void *(memset)(void *s, int c, size_t n)
{
   unsigned char *us = s, uc = c;
#ifndef _OPTIMIZED_FOR_SIZE
   unsigned long buffer, *aligned_addr;
   size_t i;

   if (!TOO_SMALL(n) && !UNALIGNED1(s)) {
       /* If we get this far, we know that n is large and s is word-
          aligned.  */
       aligned_addr = (unsigned long *) us;
       /* Store uc into each char sized location in buffer so that
          we can set large blocks quickly.  */
       for (buffer = uc, i = 1; i < sizeof(unsigned long);
            buffer += (buffer << (i * CHAR_BIT)), i << 1);
       while (n >= BLOCKSIZE * 4) {
           *aligned_addr++ = buffer;
           *aligned_addr++ = buffer;
           *aligned_addr++ = buffer;
           *aligned_addr++ = buffer;
           n -= 4 * BLOCKSIZE;
       }
       while (n >= BLOCKSIZE) {
           *aligned_addr++ = buffer;
           n -= BLOCKSIZE;
       }
       /* Pick up the remainder with a bytewise loop.  */
       us = (unsigned char *) aligned_addr;
   }
#endif
   while (n--)
       *us++ = uc;
   return s;
}

/* END OF FILE */

Gregory Pietsch


------------------------------------------------------- This SF.Net email is sponsored by BEA Weblogic Workshop FREE Java Enterprise J2EE developer tools! Get your free copy of BEA WebLogic Workshop 8.1 today. http://ads.osdn.com/?ad_id=4721&alloc_id=10040&op=click _______________________________________________ Freedos-devel mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/freedos-devel

Reply via email to