Browse Source

Major update to string handling. strcmp and friends were horribly
broken. They now test out as working properly.
-Erik

Eric Andersen 23 years ago
parent
commit
8187b0ccda
6 changed files with 257 additions and 483 deletions
  1. 4 4
      Makefile
  2. 2 11
      include/errno.h
  3. 6 4
      libc/string/Makefile
  4. 116 464
      libc/string/string.c
  5. 21 0
      test/string/Makefile
  6. 108 0
      test/string/testcopy.c

+ 4 - 4
Makefile

@@ -24,7 +24,7 @@ DIRS = error getent malloc misc regex stdio \
 	    string termios time sysdeps #rpc
 all: libc.a
 
-libc.a: subdirs headers
+libc.a: headers subdirs
 	@echo
 	@echo Finally finished compiling...
 	@echo
@@ -32,9 +32,9 @@ libc.a: subdirs headers
 
 
 headers: dummy
-	@if [ ! -L "include/asm" ]; then ln -s /usr/src/linux/include/asm include/asm ; fi
-	@if [ ! -L "include/net" ]; then ln -s /usr/src/linux/include/net include/net ; fi
-	@if [ ! -L "include/linux" ]; then ln -s /usr/src/linux/include/linux include/linux ; fi
+	@if [ ! -L "include/asm" ]; then ln -s /usr/include/asm include/asm ; fi
+	@if [ ! -L "include/net" ]; then ln -s /usr/include/net include/net ; fi
+	@if [ ! -L "include/linux" ]; then ln -s /usr/include/linux include/linux ; fi
 
 tags:
 	ctags -R

+ 2 - 11
include/errno.h

@@ -4,23 +4,14 @@
 #include <features.h>
 #include <linux/errno.h>
 
-#ifdef  __USE_BSD
 extern int sys_nerr;
 extern char *sys_errlist[];
-#endif
-#ifdef  __USE_GNU
-extern int _sys_nerr;
-extern char *_sys_errlist[];
-#endif
 
+#define _sys_nerr sys_nerr
+#define _sys_errlist sys_errlist
 
 extern int	errno;
-
-__BEGIN_DECLS
-
 extern void	perror __P ((__const char* __s));
 extern char*	strerror __P ((int __errno));
 
-__END_DECLS
-
 #endif

+ 6 - 4
libc/string/Makefile

@@ -26,11 +26,13 @@ LIBC=$(TOPDIR)libc.a
 
 MSRC=string.c
 MOBJ=strlen.o strcat.o strcpy.o strcmp.o strncat.o strncpy.o strncmp.o \
-	strchr.o strrchr.o strdup.o memcpy.o memccpy.o memchr.o memset.o \
-	memcmp.o memmove.o movedata.o
+	strchr.o strrchr.o strdup.o memcpy.o memccpy.o memset.o \
+	memmove.o
+
 CSRC=strpbrk.c strsep.c strstr.c strtok.c strcspn.c \
-    strspn.c strcasecmp.c strncasecmp.c config.c
-COBJS=$(patsubst %.c,%.o, $(CFILES))
+	config.c memcmp.c memchr.c strspn.c strcasecmp.c \
+	strncasecmp.c
+COBJS=$(patsubst %.c,%.o, $(CSRC))
 
 all: $(MOBJ) $(COBJS) $(LIBC)
 

+ 116 - 464
libc/string/string.c

@@ -6,21 +6,10 @@
 #include <string.h>
 #include <malloc.h>
 
-#ifdef __AS386_16__
-#if __FIRST_ARG_IN_AX__
-#define BCC_AX_ASM	/* BCC Assembler that can cope with arg in AX  */
-#else
-#define BCC_AX_ASM
-#define BCC_ASM		/* Use 16 bit BCC assembler */
-#endif
-
-#define PARANOID	/* Include extra code for cld and ES register */
-#endif
-
 /* This is a basic string package; it includes the most used functions
 
    strlen strcat strcpy strcmp strncat strncpy strncmp strchr strrchr strdup
-   memcpy memccpy memchr memset memcmp memmove
+   memcpy memccpy memset memmove
 
    These functions are in seperate files.
     strpbrk.o strsep.o strstr.o strtok.o strcspn.o
@@ -30,56 +19,18 @@
 /********************** Function strlen ************************************/
 
 #ifdef L_strlen
-size_t strlen(str)
-const char * str;
+size_t strlen(const char * str)
 {
-#ifdef BCC_AX_ASM
-#asm
-#if !__FIRST_ARG_IN_AX__
-  mov	bx,sp
-#endif
-  push	di
-
-#ifdef PARANOID
-  push	es
-  push	ds	; Im not sure if this is needed, so just in case.
-  pop	es
-  cld
-#endif		! This is almost the same as memchr, but it can
-		! stay as a special.
-
-#if __FIRST_ARG_IN_AX__
-  mov	di,ax
-#else
-  mov	di,[bx+2]
-#endif
-  mov	cx,#-1
-  xor	ax,ax
-  repne
-  scasb
-  not	cx
-  dec	cx
-  mov	ax,cx
-
-#ifdef PARANOID
-  pop	es
-#endif
-  pop	di
-#endasm
-#else
    register char * p =(char *) str;
    while(*p) p++;
    return p-str;
-#endif  /* ifdef BCC_AX_ASM */
 }
 #endif
 
 /********************** Function strcat ************************************/
 
 #ifdef L_strcat
-char * strcat(d, s)
-char *d; 
-const char * s;
+char * strcat(char *d, const char * s)
 {
    (void) strcpy(d+strlen(d), s);
    return d;
@@ -89,9 +40,7 @@ const char * s;
 /********************** Function strcpy ************************************/
 
 #ifdef L_strcpy
-char * strcpy(d, s)
-char *d;
-const char * s;
+char * strcpy( char *d, const char * s)
 {
    /* This is probably the quickest on an 8086 but a CPU with a cache will
     * prefer to do this in one pass */
@@ -102,68 +51,29 @@ const char * s;
 /********************** Function strcmp ************************************/
 
 #ifdef L_strcmp
-int strcmp(d, s)
-const char *d;
-const char * s;
+int strcmp(const char *d, const char * s)
 {
-  /* There are a number of ways to do this and it really does depend on the
-     types of strings given as to which is better, nevertheless the Glib
-     method is quite reasonable so we'll take that */
-
-#ifdef BCC_AX_ASM
-#asm
-  mov	bx,sp
-  push	di
-  push	si
-
-#ifdef PARANOID
-  push	es
-  push	ds	; Im not sure if this is needed, so just in case.
-  pop	es
-  cld
-#endif
-
-#if __FIRST_ARG_IN_AX__
-  mov	di,ax		; dest
-  mov	si,[bx+2]	; source
-#else
-  mov	di,[bx+2]	; dest
-  mov	si,[bx+4]	; source
-#endif
-sc_1:
-  lodsb
-  scasb
-  jne	sc_2		; If bytes are diff skip out.
-  testb	al,al
-  jne	sc_1		; If this byte in str1 is nul the strings are equal
-  xor	ax,ax		; so return zero
-  jmp	sc_3
-sc_2:
-  sbb	ax,ax		; Collect correct val (-1,1).
-  orb	al,#1
-sc_3:
-
-#ifdef PARANOID
-  pop	es
-#endif
-  pop	si
-  pop	di
-#endasm
-#else /* ifdef BCC_AX_ASM */
-   register char *s1=(char *)d, *s2=(char *)s, c1,c2;
-   while((c1= *s1++) == (c2= *s2++) && c1 );
-   return c1 - c2;
-#endif /* ifdef BCC_AX_ASM */
+    register const unsigned char *s1 = (const unsigned char *) d;
+    register const unsigned char *s2 = (const unsigned char *) s;
+    unsigned register char c1, c2;
+
+    do
+    {
+	c1 = (unsigned char) *s1++;
+	c2 = (unsigned char) *s2++;
+	if (c1 == '\0')
+	    return c1 - c2;
+    }
+    while (c1 == c2);
+
+    return c1 - c2;
 }
 #endif
 
 /********************** Function strncat ************************************/
 
 #ifdef L_strncat
-char * strncat(d, s, l)
-char *d;
-const char *s;
-size_t l;
+char * strncat( char *d, const char *s, size_t l)
 {
    register char *s1=d+strlen(d), *s2;
    
@@ -182,86 +92,110 @@ size_t l;
 /********************** Function strncpy ************************************/
 
 #ifdef L_strncpy
-char * strncpy(d, s, l)		/* FIXME need the fast version of this */
-char *d;
-const char *s;
-size_t l;
+char * strncpy ( char *s1, const char *s2, size_t n)
 {
-   register char *s1=d;
-   register const char *s2=s;
-   while(l > 0)
-   {
-      l--;
-      if( (*s1++ = *s2++) == '\0')
-         break;
-   }
-
-   /* This _is_ correct strncpy is supposed to zap */
-   for(; l>0; l--) *s1++ = '\0';
-   return d;
+    register char c;
+    char *s = s1;
+
+    --s1;
+
+    if (n >= 4)
+    {
+	size_t n4 = n >> 2;
+
+	for (;;)
+	{
+	    c = *s2++;
+	    *++s1 = c;
+	    if (c == '\0')
+		break;
+	    c = *s2++;
+	    *++s1 = c;
+	    if (c == '\0')
+		break;
+	    c = *s2++;
+	    *++s1 = c;
+	    if (c == '\0')
+		break;
+	    c = *s2++;
+	    *++s1 = c;
+	    if (c == '\0')
+		break;
+	    if (--n4 == 0)
+		goto last_chars;
+	}
+	n = n - (s1 - s) - 1;
+	if (n == 0)
+	    return s;
+	goto zero_fill;
+    }
+
+last_chars:
+    n &= 3;
+    if (n == 0)
+	return s;
+
+    do
+    {
+	c = *s2++;
+	*++s1 = c;
+	if (--n == 0)
+	    return s;
+    }
+    while (c != '\0');
+
+zero_fill:
+    do
+	*++s1 = '\0';
+    while (--n > 0);
+
+    return s;
 }
 #endif
 
 /********************** Function strncmp ************************************/
 
 #ifdef L_strncmp
-int strncmp(d, s, l)
-const char *d, *s;
-size_t l;
+int strncmp (const char *s1, const char *s2, size_t n)
 {
-#ifdef BCC_AX_ASM
-#asm
-  mov	bx,sp
-  push	si
-  push	di
-
-#ifdef PARANOID
-  push	es
-  push	ds	! Im not sure if this is needed, so just in case.
-  pop	es
-  cld
-#endif
-
-#if __FIRST_ARG_IN_AX__
-  mov	si,ax
-  mov	di,[bx+2]
-  mov	cx,[bx+4]
-#else
-  mov	si,[bx+2]	! Fetch
-  mov	di,[bx+4]
-  mov	cx,[bx+6]
-#endif
-
-  inc	cx
-lp1:
-  dec	cx
-  je	lp2
-  lodsb
-  scasb
-  jne	lp3
-  testb	al,al
-  jne	lp1
-lp2:
-  xor	ax,ax
-  jmp	lp4
-lp3:
-  sbb	ax,ax
-  or	al,#1
-lp4:
-
-#ifdef PARANOID
-  pop	es
-#endif
-  pop	di
-  pop	si
-#endasm
-#else
-   register char c1=0, c2=0;
-   while(l-- >0)
-      if( (c1= *d++) != (c2= *s++) || c1 == '\0' )
-         break;
-   return c1-c2;
-#endif
+  unsigned register char c1 = '\0';
+  unsigned register char c2 = '\0';
+
+  if (n >= 4)
+    {
+      size_t n4 = n >> 2;
+      do
+	{
+	  c1 = (unsigned char) *s1++;
+	  c2 = (unsigned char) *s2++;
+	  if (c1 == '\0' || c1 != c2)
+	    return c1 - c2;
+	  c1 = (unsigned char) *s1++;
+	  c2 = (unsigned char) *s2++;
+	  if (c1 == '\0' || c1 != c2)
+	    return c1 - c2;
+	  c1 = (unsigned char) *s1++;
+	  c2 = (unsigned char) *s2++;
+	  if (c1 == '\0' || c1 != c2)
+	    return c1 - c2;
+	  c1 = (unsigned char) *s1++;
+	  c2 = (unsigned char) *s2++;
+	  if (c1 == '\0' || c1 != c2)
+	    return c1 - c2;
+	} while (--n4 > 0);
+      n &= 3;
+    }
+
+  while (n > 0)
+    {
+      c1 = (unsigned char) *s1++;
+      c2 = (unsigned char) *s2++;
+      if (c1 == '\0' || c1 != c2)
+	return c1 - c2;
+      n--;
+    }
+
+  return c1 - c2;
 }
 #endif
 
@@ -273,37 +207,6 @@ strchr(s, c)
 const char * s;
 int c;
 {
-#ifdef BCC_AX_ASM
-#asm
-  mov	bx,sp
-  push	si
-#if __FIRST_ARG_IN_AX__
-  mov	bx,[bx+2]
-  mov	si,ax
-#else
-  mov	si,[bx+2]
-  mov	bx,[bx+4]
-#endif
-  xor	ax,ax
-
-#ifdef PARANOID
-  cld
-#endif
-
-in_loop:
-  lodsb
-  cmp	al,bl
-  jz	got_it
-  or	al,al
-  jnz	in_loop
-  pop	si
-  ret
-got_it:
-  lea	ax,[si-1]
-  pop	si
-
-#endasm
-#else /* ifdef BCC_AX_ASM */
    register char ch;
    for(;;)
    {
@@ -311,7 +214,6 @@ got_it:
      if( ch == 0 ) return 0;
      s++;
    }
-#endif /* ifdef BCC_AX_ASM */
 }
 #endif
 
@@ -361,52 +263,9 @@ void *d;
 const void *s;
 size_t l;
 {
-#ifdef BCC_AX_ASM
-#asm
-  mov	bx,sp
-  push	di
-  push	si
-
-#ifdef PARANOID
-  push	es
-  push	ds	; Im not sure if this is needed, so just in case.
-  pop	es
-  cld
-#endif
-
-#if __FIRST_ARG_IN_AX__
-  mov	di,ax		; dest
-  mov	si,[bx+2]	; source
-  mov	cx,[bx+4]	; count
-#else
-  mov	di,[bx+2]	; dest
-  mov	si,[bx+4]	; source
-  mov	cx,[bx+6]	; count
-
-  mov	ax,di
-#endif
-  		; If di is odd mov 1 byte before doing word move
-		; this will speed slightly but
-		; NB 8086 has no problem with mis-aligned access.
-
-  shr	cx,#1	; Do this faster by doing a mov word
-  rep
-  movsw
-  adc	cx,cx	; Retrieve the leftover 1 bit from cflag.
-  rep
-  movsb
-
-#ifdef PARANOID
-  pop	es
-#endif
-  pop	si
-  pop	di
-#endasm
-#else /* ifdef BCC_AX_ASM */
    register char *s1=d, *s2=(char *)s;
    for( ; l>0; l--) *((unsigned char*)s1++) = *((unsigned char*)s2++);
    return d;
-#endif /* ifdef BCC_AX_ASM */
 }
 #endif
 
@@ -427,59 +286,6 @@ size_t l;
 }
 #endif
 
-/********************** Function memchr ************************************/
-
-#ifdef L_memchr
-void * memchr(str, c, l)
-const void * str;
-int c;
-size_t l;
-{
-#ifdef BCC_ASM
-#asm
-  mov	bx,sp
-  push	di
-
-#ifdef PARANOID
-  push	es
-  push	ds	; Im not sure if this is needed, so just in case.
-  pop	es
-  cld
-#endif
-
-  mov	di,[bx+2]
-  mov	ax,[bx+4]
-  mov	cx,[bx+6]
-  test	cx,cx
-  je	is_z	! Zero length, do not find.
-
-  repne		! Scan
-  scasb
-  jne	is_z	! Not found, ret zero
-  dec	di	! Adjust ptr
-  mov	ax,di	! return
-  jmp	xit
-is_z:
-  xor	ax,ax
-xit:
-
-#ifdef PARANOID
-  pop	es
-#endif
-  pop	di
-#endasm
-#else /* ifdef BCC_ASM */
-   register char *p=(char *)str;
-   while(l-- > 0)
-   {
-      if(*p == c) return p;
-      p++;
-   }
-   return 0;
-#endif /* ifdef BCC_ASM */
-}
-#endif
-
 /********************** Function memset ************************************/
 
 #ifdef L_memset
@@ -488,109 +294,9 @@ void * str;
 int c;
 size_t l;
 {
-#ifdef BCC_AX_ASM
-#asm
-  mov	bx,sp
-  push	di
-
-#ifdef PARANOID
-  push	es
-  push	ds	; Im not sure if this is needed, so just in case.
-  pop	es
-  cld
-#endif
-
-#if __FIRST_ARG_IN_AX__
-  mov	di,ax		; Fetch
-  mov	ax,[bx+2]
-  mov	cx,[bx+4]
-#else
-  mov	di,[bx+2]	; Fetch
-  mov	ax,[bx+4]
-  mov	cx,[bx+6]
-#endif
-
-; How much difference does this alignment make ?
-; I don`t think it`s significant cause most will already be aligned.
-
-;  test	cx,cx		; Zero size - skip
-;  je	xit
-;
-;  test	di,#1		; Line it up
-;  je	s_1
-;  stosb
-;  dec	cx
-;s_1:
-
-  mov	ah,al		; Replicate byte
-  shr	cx,#1		; Do this faster by doing a sto word
-  rep			; Bzzzzz ...
-  stosw
-  adc	cx,cx		; Retrieve the leftover 1 bit from cflag.
-
-  rep			; ... z
-  stosb
-
-xit:
-  mov	ax,[bx+2]
-#ifdef PARANOID
-  pop	es
-#endif
-  pop	di
-#endasm
-#else /* ifdef BCC_AX_ASM */
    register char *s1=str;
    while(l-->0) *s1++ = c;
    return str;
-#endif /* ifdef BCC_AX_ASM */
-}
-#endif
-
-/********************** Function memcmp ************************************/
-
-#ifdef L_memcmp
-int memcmp(s, d, l)
-const void *s, *d;
-size_t l;
-{
-#ifdef BCC_ASM
-#asm
-  mov	bx,sp
-  push	di
-  push	si
-
-#ifdef PARANOID
-  push	es
-  push	ds	! Im not sure if this is needed, so just in case.
-  pop	es
-  cld
-#endif
-
-  mov	si,[bx+2]	! Fetch
-  mov	di,[bx+4]
-  mov	cx,[bx+6]
-  xor	ax,ax
-
-  rep			! Bzzzzz
-  cmpsb
-  je	xit		! All the same!
-  sbb	ax,ax
-  sbb	ax,#-1		! choose +/-1
-xit:
-#ifdef PARANOID
-  pop	es
-#endif
-  pop	si
-  pop	di
-#endasm
-#else /* ifdef BCC_ASM */
-   register const char *s1=d, *s2=s;
-   register char c1=0, c2=0;
-   while(l-- > 0)
-      if( (c1= *s1++) != (c2= *s2++) )
-         break;
-   return c1-c2;
-#endif /* ifdef BCC_ASM */
 }
 #endif
 
@@ -615,60 +321,6 @@ size_t l;
 }
 #endif
 
-/********************** Function movedata ***********************************/
-
-#ifdef L_movedata
-
-/* NB There isn't any C version of this function ... */
-
-#ifdef BCC_AX_ASM
-void
-__movedata(srcseg, srcoff, destseg, destoff, len)
-unsigned int srcseg, srcoff, destseg, destoff, len;
-{
-#asm
-  push	bp
-  mov	bp,sp
-  push	si
-  push	di
-  push	ds
-#ifdef PARANOID
-  push	es
-  cld
-#endif
-
-  ! sei			! Are we _really_ paranoid ?
-
-#if !__FIRST_ARG_IN_AX__
-  mov	ds,[bp+4]	! Careful, [bp+xx] is SS based.
-  mov	si,[bp+6]
-  mov	es,[bp+8]
-  mov	di,[bp+10]
-  mov	cx,[bp+12]
-#else
-  mov	ds,ax
-  mov	si,[bp+4]
-  mov	es,[bp+6]
-  mov	di,[bp+8]
-  mov	cx,[bp+10]
-#endif
-  rep
-   movsb
-
-  ! cli			! Are we _really_ paranoid ?
-  
-#ifdef PARANOID
-  pop	es
-#endif
-  pop	ds
-  pop	di
-  pop	si
-  pop	bp
-#endasm
-}
-#endif
-
-#endif
 
 /********************** THE END ********************************************/
 

+ 21 - 0
test/string/Makefile

@@ -20,6 +20,7 @@ endif
 STRIP    = $(STRIPTOOL) --remove-section=.note --remove-section=.comment $@
 
 TARGETS=string string_glibc
+TARGETS+=testcopy testcopy_glibc
 
 all: $(TARGETS)
 
@@ -43,6 +44,26 @@ string_glibc: string.c Makefile $(TOPDIR)libc.a
 	-./$@
 	-@ echo " "
 
+testcopy: testcopy.c Makefile $(TOPDIR)libc.a
+	-@ echo "-------"
+	-@ echo " "
+	-@ echo "Compiling vs uCLibc: "
+	-@ echo " "
+	$(CC) $(XCFLAGS) -c $< -o $@.o
+	$(CC) $(XLDFLAGS) $@.o -o $@ $(EXTRA_LIBS)
+	-./$@
+	-@ echo " "
+
+testcopy_glibc: testcopy.c Makefile $(TOPDIR)libc.a
+	-@ echo "-------"
+	-@ echo " "
+	-@ echo "Compiling vs GNU libc: "
+	-@ echo " "
+	$(CC) $(YCFLAGS) -c $< -o $@.o
+	$(CC) $(YLDFLAGS) --static $@.o -o $@
+	-./$@
+	-@ echo " "
+
 clean:
 	rm -f *.[oa] *~ core $(TARGETS)
 

+ 108 - 0
test/string/testcopy.c

@@ -0,0 +1,108 @@
+/* Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
+   Contributed by Torbjorn Granlund (tege@sics.se).
+
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+
+int main(int argc, char **argv)
+{
+  char *mem, *memp;
+  char *rand_mem;
+  char *lo_around, *hi_around;
+  int size, max_size;
+  int src_off, dst_off;
+  int i;
+  int space_around = 10;
+
+  max_size = 256;
+
+  mem = malloc (max_size + 2 * max_size + 2 * space_around);
+  rand_mem = malloc (max_size);
+  lo_around = malloc (space_around);
+  hi_around = malloc (space_around);
+  memp = mem + space_around;
+
+  /* Fill RAND_MEM with random bytes, each non-zero.  */
+  for (i = 0; i < max_size; i++)
+    {
+      int x;
+      do
+	x = rand ();
+      while (x == 0);
+      rand_mem[i] = x;
+    }
+
+  for (size = 0; size < max_size; size++)
+    {
+      printf("phase %d\n", size);
+      for (src_off = 0; src_off <= 16; src_off++)
+	{
+	  for (dst_off = 0; dst_off <= 16; dst_off++)
+	    {
+	      /* Put zero around the intended destination, to check
+		 that it's not clobbered.  */
+	      for (i = 1; i < space_around; i++)
+		{
+		  memp[dst_off - i] = 0;
+		  memp[dst_off + size - 1 + i] = 0;
+		}
+
+	      /* Fill the source area with known contents.  */
+	      for (i = 0; i < size; i++)
+		memp[src_off + i] = rand_mem[i];
+
+	      /* Remember the contents around the destination area.
+		 (It might not be what we wrote some lines above, since
+		 the src area and the dst area overlap.)  */
+	      for (i = 1; i < space_around; i++)
+		{
+		  lo_around[i] = memp[dst_off - i];
+		  hi_around[i] = memp[dst_off + size - 1 + i];
+		}
+
+	      memmove (memp + dst_off, memp + src_off, size);
+
+	      /* Check that the destination area has the same
+		 contents we wrote to the source area.  */
+	      for (i = 0; i < size; i++)
+		{
+		  if (memp[dst_off + i] != rand_mem[i])
+		    abort ();
+		}
+
+	      /* Check that the area around the destination is not
+		 clobbered.  */
+	      for (i = 1; i < space_around; i++)
+		{
+		  if (memp[dst_off - i] != lo_around[i])
+		    abort ();
+		  if (memp[dst_off + size - 1 + i] != hi_around[i])
+		    abort ();
+		}
+	    }
+	}
+    }
+
+  puts ("Test succeeded.");
+
+  return 0;
+}