[comp.sources.misc] v19i027: dmake - dmake version 3.7, Part06/37

dvadura@watdragon.waterloo.edu (Dennis Vadura) (05/11/91)

Submitted-by: Dennis Vadura <dvadura@watdragon.waterloo.edu>
Posting-number: Volume 19, Issue 27
Archive-name: dmake/part06
Supersedes: dmake-3.6: Volume 15, Issue 52-77

---- Cut Here and feed the following to sh ----
#!/bin/sh
# this is dmake.shar.06 (part 6 of a multipart archive)
# do not concatenate these parts, unpack them in order with /bin/sh
# file dmake/dbug/malloc/mallopt.c continued
#
if test ! -r _shar_seq_.tmp; then
	echo 'Please unpack part 1 first!'
	exit 1
fi
(read Scheck
 if test "$Scheck" != 6; then
	echo Please unpack part "$Scheck" next!
	exit 1
 else
	exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test -f _shar_wnt_.tmp; then
sed 's/^X//' << 'SHAR_EOF' >> 'dmake/dbug/malloc/mallopt.c' &&
X * You may copy, distribute, and use this software as long as this
X * copyright statement is not removed.
X */
#include <stdio.h>
#include <fcntl.h>
#include "malloc.h"
X
/*
X * Function:	mallopt()
X *
X * Purpose:	to set options for the malloc debugging library
X *
X * Arguments:	none
X *
X * Returns:	nothing of any value
X *
X * Narrative:	
X *
X */
X
#ifndef lint
static
char rcs_hdr[] = "$Id: mallopt.c,v 1.6 90/08/29 22:23:36 cpcahil Exp $";
#endif
X
int
mallopt(cmd,value)
X	int			  cmd;
X	union malloptarg	  value;
{
X	int			  i;
X	extern int		  malloc_checking;
X	extern char		* malloc_data_start;
X	extern int		  malloc_errfd;
X	extern int		  malloc_fatal_level;
X	void			  malloc_init();
X	extern int		  malloc_warn_level;
X	register char		* s;
X
X	/*
X 	 * If not initialized...
X	 */
X	if( malloc_data_start == (char *) 0)
X	{
X		malloc_init();
X	}
X
X
X	switch(cmd)
X	{
X		case MALLOC_WARN:
X			malloc_warn_level = value.i;
X			break;
X
X		case MALLOC_FATAL:
X			malloc_fatal_level = value.i;
X			break;
X
X		case MALLOC_CKCHAIN:
X			malloc_checking = value.i;
X			break;
X
X		case MALLOC_ERRFILE:
X			
X			i = open(value.str,O_CREAT|O_APPEND|O_WRONLY,0666);
X			if( i == -1 )
X			{
X				(void) write(2,
X					  "Unable to open malloc error file: ",
X					  (unsigned) 34);
X				for(s=value.str; *s; s++)
X				{
X					/* do nothing */;
X				}
X				(void) write(2,value.str,
X					     (unsigned)(s-value.str));
X				(void) write(2,"\n",(unsigned)1);
X			}
X			else
X			{
X				if( malloc_errfd != 2 )
X				{
X					(void) close(malloc_errfd);
X				}
X				malloc_errfd = i;
X			}
X			
X			break;
X
X		default:
X			return(1);
X	}
X
X	return(0);
}
X
/*
X * $Log:	mallopt.c,v $
X * Revision 1.6  90/08/29  22:23:36  cpcahil
X * fixed mallopt to use a union as an argument.
X * 
X * Revision 1.5  90/08/29  21:22:51  cpcahil
X * miscellaneous lint fixes
X * 
X * Revision 1.4  90/05/11  00:13:10  cpcahil
X * added copyright statment
X * 
X * Revision 1.3  90/02/25  11:03:26  cpcahil
X * changed to return int so that it agrees with l libmalloc.a's mallopt()
X * 
X * Revision 1.2  90/02/25  11:01:21  cpcahil
X * added support for malloc chain checking.
X * 
X * Revision 1.1  90/02/24  21:50:24  cpcahil
X * Initial revision
X * 
X * Revision 1.1  90/02/24  17:10:53  cpcahil
X * Initial revision
X * 
X */
SHAR_EOF
chmod 0640 dmake/dbug/malloc/mallopt.c ||
echo 'restore of dmake/dbug/malloc/mallopt.c failed'
Wc_c="`wc -c < 'dmake/dbug/malloc/mallopt.c'`"
test 2281 -eq "$Wc_c" ||
	echo 'dmake/dbug/malloc/mallopt.c: original size 2281, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= dmake/dbug/malloc/memory.c ==============
if test -f 'dmake/dbug/malloc/memory.c' -a X"$1" != X"-c"; then
	echo 'x - skipping dmake/dbug/malloc/memory.c (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/malloc/memory.c' &&
/*
X * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).  
X * You may copy, distribute, and use this software as long as this
X * copyright statement is not removed.
X */
X
#ifndef lint
static
char rcs_hdr[] = "$Id: memory.c,v 1.7 90/08/29 21:27:58 cpcahil Exp $";
#endif
X
void malloc_check_data();
X
char *
memccpy(ptr1, ptr2, ch, len)
X	register char	* ptr1;
X	register char	* ptr2;
X	int		  len;
X	int		  ch;
{
X	int		  check;
X	register int	  i;
X	char		* rtn;
X
X	/*
X	 * I know that the assignment could be done in the following, but
X	 * I wanted to perform a check before any assignment, so first I 
X	 * determine the length, check the pointers and then do the assignment.
X	 */
X	for( i=0; (i < len) && (ptr2[i] != ch); i++)
X	{
X	}
X	if( ptr2[i] == ch )
X	{
X		check = i+1;
X	}
X	else
X	{
X		check = len;
X	}
X
X	malloc_check_data("memccpy", ptr1, check);
X	malloc_check_data("memccpy", ptr2, check);
X
X	/*
X	 * if we found the character...
X 	 */
X
X	if( i < len )
X	{
X		rtn = ptr1+i+1;
X		i++;
X	}
X	else
X	{
X		rtn = (char *) 0;
X	}
X
X 	while( i-- )
X	{
X		*(ptr1++) = *(ptr2++);
X	}
X	
X	return(rtn);
}
X
char *
memchr(ptr1,ch,len)
X	register char	* ptr1;
X	register int	  ch;
X	int		  len;
{
X	int		  i;
X
X	for( i=0; (i < len) && (ptr1[i] != (char) ch); i++)
X	{
X	}
X
X	malloc_check_data("memchr", ptr1, i);
X
X	if( i < len )
X	{
X		return( ptr1+i );
X	}
X	else
X	{
X		return( (char *) 0);	
X	}
}
X
char *
memcpy(ptr1, ptr2, len)
X	register char	* ptr1;
X	register char	* ptr2;
X	register int	  len;
{
X	char		* rtn = ptr1;
X
X	malloc_check_data("memcpy", ptr1, len);
X	malloc_check_data("memcpy", ptr2, len);
X
X	/*
X	 * while the normal memcpy does not guarrantee that it will 
X	 * handle overlapping memory correctly, we will try...
X	 */
X	if( ptr1 > ptr2  && ptr1 < (ptr2+len))
X	{
X		ptr1 += (len-1);
X		ptr2 += (len-1);
X		while( len-- > 0 )
X		{
X			*(ptr1--) = *(ptr2--);
X		}
X	}
X	else
X	{
X		while( len-- > 0 )
X		{
X			*(ptr1++) = *(ptr2++);
X		}
X	}
X	
X	return(rtn);
}
X
int
memcmp(ptr1, ptr2, len)
X	register char	* ptr1;
X	register char	* ptr2;
X	register int	  len;
{
X	malloc_check_data("memcpy", ptr1, len);
X	malloc_check_data("memcpy", ptr2, len);
X
X	while( --len >= 0  && (*ptr1 == *ptr2) )
X	{
X		ptr1++;
X		ptr2++;
X	}
X
X	/* 
X	 * If stopped by len, return zero
X	 */
X	if( len < 0 )
X	{
X		return(0);
X	}
X
X	return( *ptr1 - *ptr2 );
}
X
char * 
memset(ptr1, ch, len)
X	register char	* ptr1;
X	register int	  ch;
X	register int	  len;
{
X	char		* rtn = ptr1;
X
X	malloc_check_data("memcpy", ptr1, len);
X
X	while( len-- )
X	{
X		*(ptr1++) = ch;
X	}
X
X	return(rtn);
}
X
char *
bcopy(ptr2,ptr1,len)
X	char		* ptr2;
X	char		* ptr1;
X	int		  len;
{
X	return(memcpy(ptr1,ptr2,len));
}
X
char *
bzero(ptr1,len)
X	char		* ptr1;
X	int		  len;
{
X	return(memset(ptr1,'\0',len));
}
X
int
bcmp(ptr2, ptr1, len)
X	char		* ptr1;
X	char		* ptr2;
X	int		  len;
{
X	return( memcmp(ptr1,ptr2,len) );
}
X
/*
X * $Log:	memory.c,v $
X * Revision 1.7  90/08/29  21:27:58  cpcahil
X * fixed value of check in memccpy when character was not found.
X * 
X * Revision 1.6  90/07/16  20:06:26  cpcahil
X * fixed several minor bugs found with Henry Spencer's string/mem tester 
X * program.
X * 
X * 
X * Revision 1.5  90/05/11  15:39:36  cpcahil
X * fixed bug in memccpy().
X * 
X * Revision 1.4  90/05/11  00:13:10  cpcahil
X * added copyright statment
X * 
X * Revision 1.3  90/02/24  21:50:29  cpcahil
X * lots of lint fixes
X * 
X * Revision 1.2  90/02/24  17:29:41  cpcahil
X * changed $Header to $Id so full path wouldnt be included as part of rcs 
X * id string
X * 
X * Revision 1.1  90/02/22  23:17:43  cpcahil
X * Initial revision
X * 
X */
SHAR_EOF
chmod 0640 dmake/dbug/malloc/memory.c ||
echo 'restore of dmake/dbug/malloc/memory.c failed'
Wc_c="`wc -c < 'dmake/dbug/malloc/memory.c'`"
test 3505 -eq "$Wc_c" ||
	echo 'dmake/dbug/malloc/memory.c: original size 3505, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= dmake/dbug/malloc/mlc_chk.c ==============
if test -f 'dmake/dbug/malloc/mlc_chk.c' -a X"$1" != X"-c"; then
	echo 'x - skipping dmake/dbug/malloc/mlc_chk.c (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/malloc/mlc_chk.c' &&
/*
X * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).  
X * You may copy, distribute, and use this software as long as this
X * copyright statement is not removed.
X */
X
#include <stdio.h>
#include "malloc.h"
#include "debug.h"
X
#ifndef lint
static
char rcs_hdr[] = "$Id: malloc_chk.c,v 1.5 90/08/29 22:23:48 cpcahil Exp $";
#endif
X
extern struct mlist	  malloc_start;
extern struct mlist	* malloc_end;
extern char		* malloc_data_start;
extern char		* malloc_data_end;
X
/*
X * Function:	malloc_in_arena()
X *
X * Purpose:	to verify address is within malloc arena.
X *
X * Arguments:	ptr	- pointer to verify
X *
X * Returns:	TRUE	- if pointer is within malloc area
X *		FALSE	- otherwise
X *
X * Narrative:
X *   IF pointer is >= malloc area start AND <= malloc area end
X *      return TRUE
X *   ELSE
X *      return FALSE
X *
X * Mod History:	
X *   90/01/24	cpcahil		Initial revision.
X */
int
malloc_in_arena(ptr)
X	char	* ptr;
{
X	extern char	* malloc_data_start;
X	extern char	* malloc_data_end;
X	int		  rtn = 0;
X
X	if( ptr >= malloc_data_start && ptr <= malloc_data_end )
X	{
X		rtn = 1;
X	}
X	
X	return(rtn);
}
X
/*
X * Function:	malloc_check_str()
X *
X * Arguments:	func	- name of function calling this routine
X *		str	- pointer to area to check
X *
X * Purpose:	to verify that if str is within the malloc arena, the data 
X *		it points to does not extend beyond the applicable region.
X *
X * Returns:	Nothing of any use (function is void).
X *
X * Narrative:
X *   IF pointer is within malloc arena
X *      determin length of string
X *      call malloc_verify() to verify data is withing applicable region
X *   return 
X *
X * Mod History:	
X *   90/01/24	cpcahil		Initial revision.
X *   90/01/29	cpcahil		Added code to ignore recursive calls.
X */
void
malloc_check_str(func,str)
X	char		* func;
X	char		* str;
{
X	static int	  layers;
X	register char	* s;
X
X	if( (layers++ == 0) &&  malloc_in_arena(str) )
X	{
X		for( s=str; *s; s++)
X		{
X		}
X		
X		malloc_verify(func,str,s-str+1);
X	}
X
X	layers--;
}
X
/*
X * Function:	malloc_check_strn()
X *
X * Arguments:	func	- name of function calling this routine
X *		str	- pointer to area to check
X * 		len     - max length of string
X *
X * Purpose:	to verify that if str is within the malloc arena, the data 
X *		it points to does not extend beyond the applicable region.
X *
X * Returns:	Nothing of any use (function is void).
X *
X * Narrative:
X *   IF pointer is within malloc arena
X *      determin length of string
X *      call malloc_verify() to verify data is withing applicable region
X *   return 
X *
X * Mod History:	
X *   90/01/24	cpcahil		Initial revision.
X *   90/01/29	cpcahil		Added code to ignore recursive calls.
X *   90/08/29	cpcahil		added length (for strn* functions)
X */
void
malloc_check_strn(func,str,len)
X	char		* func;
X	char		* str;
X	int		  len;
{
X	register int	  i;
X	static int	  layers;
X	register char	* s;
X
X	if( (layers++ == 0) &&  malloc_in_arena(str) )
X	{
X		for( s=str,i=0; (i < len) && *s; s++)
X		{
X		}
X		
X		malloc_verify(func,str,s-str+1);
X	}
X
X	layers--;
}
X
/*
X * Function:	malloc_check_data()
X *
X * Arguments:	func	- name of function calling this routine
X *		ptr	- pointer to area to check
X *		len 	- length to verify
X *
X * Purpose:	to verify that if ptr is within the malloc arena, the data 
X *		it points to does not extend beyond the applicable region.
X *
X * Returns:	Nothing of any use (function is void).
X *
X * Narrative:
X *   IF pointer is within malloc arena
X *      call malloc_verify() to verify data is withing applicable region
X *   return 
X *
X * Mod History:	
X *   90/01/24	cpcahil		Initial revision.
X *   90/01/29	cpcahil		Added code to ignore recursive calls.
X */
void
malloc_check_data(func,ptr,len)
X	char		* func;
X	char		* ptr;
X	int		  len;
{
X	static int	  layers;
X
X	if( layers++ == 0 )
X	{
X		DEBUG3(40,"malloc_check_data(%s,0x%x,%d) called...",
X			func,ptr,len);
X		if( malloc_in_arena(ptr) )
X		{
X			DEBUG0(10,"pointer in malloc arena, verifying...");
X			malloc_verify(func,ptr,len);
X		}
X	}
X
X	layers--;
}
X
/*
X * Function:	malloc_verify()
X *
X * Arguments:	func	- name of function calling the malloc check routines
X *		ptr	- pointer to area to check
X *		len 	- length to verify
X *
X * Purpose:	to verify that the data ptr points to does not extend beyond
X *		the applicable malloc region.  This function is only called 
X *		if it has been determined that ptr points into the malloc arena.
X *
X * Returns:	Nothing of any use (function is void).
X *
X * Narrative:
X *
X * Mod History:	
X *   90/01/24	cpcahil		Initial revision.
X */
void
malloc_verify(func,ptr,len)
X	char		* func;
X	char		* ptr;
X	int		  len;
{
X	extern struct mlist	* malloc_end;
X	extern int		  malloc_errno;
X	extern struct mlist 	  malloc_start;
X	struct mlist		* mptr;
X	
X	DEBUG3(40,"malloc_verify(%s,0x%x,%d) called...", func,ptr,len);
X	/*
X	 * Find the malloc block that includes this pointer
X	 */
X	mptr = &malloc_start;
X	while( mptr && 
X		! (((char *)mptr < ptr) && ((mptr->data+mptr->s.size) > ptr) ) )
X	{
X		mptr = mptr->next;
X	}
X
X	/*
X	 * if ptr was not in a malloc block, it must be part of
X	 *    some direct sbrk() stuff, so just return.
X	 */
X	if( ! mptr )
X	{
X		DEBUG1(10,"ptr (0x%x) not found in malloc search", ptr);
X		return;
X	}
X	
X	/*
X 	 * Now we have a valid malloc block that contains the indicated
X	 * pointer.  We must verify that it is withing the requested block
X	 * size (as opposed to the real block size which is rounded up to
X	 * allow for correct alignment).
X	 */
X
X	DEBUG4(60,"Checking  0x%x-0x%x, 0x%x-0x%x",
X			ptr, ptr+len, mptr->data, mptr->data+mptr->r_size);
X	
X	if( (ptr < mptr->data) || ((ptr+len) > (mptr->data+mptr->r_size)) )
X	{
X		DEBUG4(0,"pointer not within region 0x%x-0x%x, 0x%x-0x%x",
X			ptr, ptr+len, mptr->data, mptr->data+mptr->r_size);
X
X		malloc_errno = M_CODE_OUTOF_BOUNDS;
X		malloc_warning(func);
X	}
X
X	return;
}
X
/*
X * $Log:	malloc_chk.c,v $
X * Revision 1.5  90/08/29  22:23:48  cpcahil
X * added new function to check on strings up to a specified length 
X * and used it within several strn* functions.
X * 
X * Revision 1.4  90/05/11  00:13:09  cpcahil
X * added copyright statment
X * 
X * Revision 1.3  90/02/24  21:50:22  cpcahil
X * lots of lint fixes
X * 
X * Revision 1.2  90/02/24  17:29:38  cpcahil
X * changed $Header to $Id so full path wouldnt be included as part of rcs 
X * id string
X * 
X * Revision 1.1  90/02/24  14:57:03  cpcahil
X * Initial revision
X * 
X */
SHAR_EOF
chmod 0640 dmake/dbug/malloc/mlc_chk.c ||
echo 'restore of dmake/dbug/malloc/mlc_chk.c failed'
Wc_c="`wc -c < 'dmake/dbug/malloc/mlc_chk.c'`"
test 6308 -eq "$Wc_c" ||
	echo 'dmake/dbug/malloc/mlc_chk.c: original size 6308, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= dmake/dbug/malloc/mlc_chn.c ==============
if test -f 'dmake/dbug/malloc/mlc_chn.c' -a X"$1" != X"-c"; then
	echo 'x - skipping dmake/dbug/malloc/mlc_chn.c (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/malloc/mlc_chn.c' &&
/*
X * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).  
X * You may copy, distribute, and use this software as long as this
X * copyright statement is not removed.
X */
#include <stdio.h>
#include <fcntl.h>
#include "malloc.h"
X
/*
X * Function:	malloc_chain_check()
X *
X * Purpose:	to verify malloc chain is intact
X *
X * Arguments:	todo	- 0 - just check and return status
X *			  1 - call malloc_warn if error detected
X *
X * Returns:	0	- malloc chain intact & no overflows
X *		other	- problems detected in malloc chain
X *
X * Narrative:
X *
X * Notes:	If todo is non-zero the malloc_warn function, when called
X *		may not return (i.e. it may exit)
X *
X */
#ifndef lint
static
char rcs_hdr[] = "$Id: malloc_chn.c,v 1.4 90/05/11 00:13:09 cpcahil Exp $";
#endif
X
X
int
malloc_chain_check(todo)
X	int		  todo;
{
X	char			* func = "malloc_chain_check";
X	int			  i;
X	extern char		* malloc_data_start;
X	extern char		* malloc_data_end;
X	extern struct mlist 	* malloc_end;
X	extern int		  malloc_errno;
X	extern struct mlist	  malloc_start;
X	struct mlist		* oldptr;
X	struct mlist		* ptr;
X	int			  rtn = 0;
X
X	oldptr = &malloc_start;
X	for(ptr = malloc_start.next; ; ptr = ptr->next)
X	{
X		/*
X		 * Since the malloc chain is a forward only chain, any
X		 * pointer that we get should always be positioned in 
X		 * memory following the previous pointer.  If this is not
X		 * so, we must have a corrupted chain.
X		 */
X		if( ptr )
X		{
X			if(ptr < oldptr )
X			{
X				malloc_errno = M_CODE_CHAIN_BROKE;
X				if( todo )
X				{
X					malloc_fatal(func);
X				}
X				rtn++;
X				break;
X			}
X			oldptr = ptr;
X		}
X		else
X		{
X			if( oldptr != malloc_end )
X			{
X				/*
X				 * This should never happen.  If it does, then
X				 * we got a real problem.
X				 */
X				malloc_errno = M_CODE_NO_END;
X				if( todo )
X				{
X					malloc_fatal(func);
X				}
X				rtn++;
X			}
X			break;
X		}
X		
X		/*
X		 * verify that ptr is within the malloc region...
X		 * since we started within the malloc chain this should never
X		 * happen.
X		 */
X
X		if( ((char *)ptr < malloc_data_start) ||
X		    ((char *)ptr > malloc_data_end) )
X		{
X			malloc_errno = M_CODE_BAD_PTR;
X			if( todo )
X			{
X				malloc_fatal(func);
X			}
X			rtn++;
X			break;
X		}
X
X		/* 
X		 * verify magic flag is set
X		 */
X		
X		if( (ptr->flag&M_MAGIC) != M_MAGIC )
X		{
X			malloc_errno = M_CODE_BAD_MAGIC;
X			if( todo )
X			{
X				malloc_warning(func);
X			}
X			rtn++;
X			continue;
X		}
X
X		/* 
X		 * verify segments are correctly linked together
X		 */
X		
X		if( (ptr->prev && (ptr->prev->next != ptr) ) ||
X		    (ptr->next && (ptr->next->prev != ptr) ) ||
X		    ((ptr->next == NULL) && (ptr->prev == NULL)) )
X		{
X			malloc_errno = M_CODE_BAD_CONNECT;
X			if( todo )
X			{
X				malloc_warning(func);
X			}
X			rtn++;
X			continue;
X		}
X
X		/*
X		 * If this segment is allocated
X		 */
X
X		if( (ptr->flag & M_INUSE) != 0 )
X		{
X			/*
X			 * verify no overflow of data area
X			 */
X
X			for(i=ptr->r_size; i < ptr->s.size; i++)
X			{
X				if( ptr->data[i] != M_FILL )
X				{
X					malloc_errno = M_CODE_OVERRUN;
X					if( todo )
X					{
X						malloc_warning(func);
X					}
X					rtn++;
X					break;
X				}
X			}
X		}
X		else /* it's not allocated so */
X		{
X			/*
X			 * verify no reuse of freed data blocks
X			 */
X
X			for(i=0; i < ptr->s.size; i++)
X			{
X				if( ptr->data[i] != M_FREE_FILL )
X				{
X					malloc_errno = M_CODE_REUSE;
X					if( todo )
X					{
X						malloc_warning(func);
X					}
X					rtn++;
X					break;
X				}
X			}
X		}
X
X	} /* for(... */
X
X	return(rtn);
X
} /* malloc_chain_check(... */
SHAR_EOF
chmod 0640 dmake/dbug/malloc/mlc_chn.c ||
echo 'restore of dmake/dbug/malloc/mlc_chn.c failed'
Wc_c="`wc -c < 'dmake/dbug/malloc/mlc_chn.c'`"
test 3449 -eq "$Wc_c" ||
	echo 'dmake/dbug/malloc/mlc_chn.c: original size 3449, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= dmake/dbug/malloc/patchlevel ==============
if test -f 'dmake/dbug/malloc/patchlevel' -a X"$1" != X"-c"; then
	echo 'x - skipping dmake/dbug/malloc/patchlevel (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/malloc/patchlevel' &&
3
SHAR_EOF
chmod 0640 dmake/dbug/malloc/patchlevel ||
echo 'restore of dmake/dbug/malloc/patchlevel failed'
Wc_c="`wc -c < 'dmake/dbug/malloc/patchlevel'`"
test 2 -eq "$Wc_c" ||
	echo 'dmake/dbug/malloc/patchlevel: original size 2, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= dmake/dbug/malloc/realloc.c ==============
if test -f 'dmake/dbug/malloc/realloc.c' -a X"$1" != X"-c"; then
	echo 'x - skipping dmake/dbug/malloc/realloc.c (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/malloc/realloc.c' &&
/*
X * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).  
X * You may copy, distribute, and use this software as long as this
X * copyright statement is not removed.
X */
#include <stdio.h>
#include "malloc.h"
X
/*
X * Function:	realloc()
X *
X * Purpose:	to re-allocate a data area.
X *
X * Arguments:	cptr	- pointer to area to reallocate
X *		size	- size to change area to
X *
X * Returns:	pointer to new area (may be same area)
X *
X * Narrative:	verify pointer is within malloc region
X *		obtain mlist pointer from cptr
X *		verify magic number is correct
X *		verify inuse flag is set
X *		verify connection to adjoining segments is correct
X *		save requested size
X *		round-up size to appropriate boundry
X *		IF size is bigger than what is in this segment
X *		    try to join next segment to this segment
X *		IF size is less than what is is this segment
X *		    determine leftover amount of space
X *		ELSE
X *		    allocate new segment of size bites
X *		    IF allocation failed
X *		        return NULL
X *		    copy previous data to new segment
X *		    free previous segment
X *		    return new pointer
X *		split of extra space in this segment (if any)
X *		clear bytes beyound what they had before
X *		return pointer to data 
X */
#ifndef lint
static
char rcs_hdr[] = "$Id: realloc.c,v 1.8 90/08/29 21:22:52 cpcahil Exp $";
#endif
X
char *
realloc(cptr,size)
X	char			* cptr;
X	unsigned int		  size;
{
X	void			  free();
X	char			* func = "realloc";
X	int			  i;
X	char			* malloc();
X	extern int		  malloc_checking;
X	extern struct mlist 	* malloc_end;
X	extern int		  malloc_errno;
X	extern char		* malloc_data_end;
X	extern char		* malloc_data_start;
X	void			  malloc_join();
X	void			  malloc_memset();
X	void			  malloc_split();
X	char			* memcpy();
X	char			* new_cptr;
X	struct mlist		* ptr;
X	int			  r_size;
X
X	/*
X	 * IF malloc chain checking is on, go do it.
X	 */
X	if( malloc_checking )
X	{
X		(void) malloc_chain_check(1);
X	}
X
X	/*
X	 * verify that cptr is within the malloc region...
X	 */
X	if( cptr < malloc_data_start || cptr > malloc_data_end )
X	{
X		malloc_errno = M_CODE_BAD_PTR;
X		malloc_warning(func);
X		return (NULL);
X	}
X
X	/* 
X	 * convert pointer to mlist struct pointer.  To do this we must 
X	 * move the pointer backwards the correct number of bytes...
X	 */
X	
X	ptr = (struct mlist *) (cptr - M_SIZE);
X	
X	if( (ptr->flag&M_MAGIC) != M_MAGIC )
X	{
X		malloc_errno = M_CODE_BAD_MAGIC;
X		malloc_warning(func);
X		return(NULL);
X	}
X
X	if( ! (ptr->flag & M_INUSE) )
X	{
X		malloc_errno = M_CODE_NOT_INUSE ;
X		malloc_warning(func);
X		return(NULL);
X	}
X
X 	if( (ptr->prev && (ptr->prev->next != ptr) ) ||
X	    (ptr->next && (ptr->next->prev != ptr) ) ||
X	    ((ptr->next == NULL) && (ptr->prev == NULL)) )
X	{
X		malloc_errno = M_CODE_BAD_CONNECT;
X		malloc_warning(func);
X		return(NULL);
X	}
X
X	r_size = ++size;
X
X	M_ROUNDUP(size);
X
X	if( size > ptr->s.size )
X	{
X		malloc_join(ptr,ptr->next,1,1);
X	}
X
X	if( size > ptr->s.size )
X	{
X		/*
X		 * else we can't combine it, so lets allocate a new chunk,
X		 * copy the data and free the old chunk...
X		 */
X		new_cptr = malloc(size);
X
X		if( new_cptr == (char *) 0)
X		{
X			return(new_cptr);
X		}
X
X		if( r_size < ptr->r_size )
X		{
X			i = r_size;
X		}
X		else
X		{
X			i = ptr->r_size;
X		}
X		(void)memcpy(new_cptr,ptr->data,i);
X		free(cptr);
X		return(new_cptr);
X
X	} /* else... */
X
X	/*
X	 * save amount of real data in new segment (this will be used in the
X	 * memset later) and then save requested size of this segment.
X	 */
X
X	if( ptr->r_size < r_size )
X	{
X		i = ptr->r_size;
X	}
X	else
X	{
X		i = r_size;
X	}
X
X	ptr->r_size = r_size;
X
X	/*
X	 * split off extra free space at end of this segment, if possible...
X	 */
X
X	malloc_split(ptr);
X
X	malloc_memset( ptr->data+i, M_FILL, (int) (ptr->s.size - i));
X		
X	return(ptr->data);
X
} /* realloc(... */
X
X
/*
X * $Log:	realloc.c,v $
X * Revision 1.8  90/08/29  21:22:52  cpcahil
X * miscellaneous lint fixes
X * 
X * Revision 1.7  90/05/11  00:13:10  cpcahil
X * added copyright statment
X * 
X * Revision 1.6  90/02/25  11:01:20  cpcahil
X * added support for malloc chain checking.
X * 
X * Revision 1.5  90/02/24  21:50:31  cpcahil
X * lots of lint fixes
X * 
X * Revision 1.4  90/02/24  17:29:39  cpcahil
X * changed $Header to $Id so full path wouldnt be included as part of rcs 
X * id string
X * 
X * Revision 1.3  90/02/24  17:20:00  cpcahil
X * attempt to get rid of full path in rcs header.
X * 
X * Revision 1.2  90/02/24  15:14:20  cpcahil
X * 1. added function header 
X * 2. changed calls to malloc_warning to conform to new usage
X * 3. added setting of malloc_errno
X *  4. broke up bad pointer determination so that errno's would be more
X *    descriptive
X * 
X * Revision 1.1  90/02/22  23:17:43  cpcahil
X * Initial revision
X * 
X */
SHAR_EOF
chmod 0640 dmake/dbug/malloc/realloc.c ||
echo 'restore of dmake/dbug/malloc/realloc.c failed'
Wc_c="`wc -c < 'dmake/dbug/malloc/realloc.c'`"
test 4659 -eq "$Wc_c" ||
	echo 'dmake/dbug/malloc/realloc.c: original size 4659, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= dmake/dbug/malloc/string.c ==============
if test -f 'dmake/dbug/malloc/string.c' -a X"$1" != X"-c"; then
	echo 'x - skipping dmake/dbug/malloc/string.c (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/malloc/string.c' &&
/*
X * (c) Copyright 1990 Conor P. Cahill (uunet!virtech!cpcahil).  
X * You may copy, distribute, and use this software as long as this
X * copyright statement is not removed.
X */
X
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include "malloc.h"
X
#ifndef lint
static
char rcs_hdr[] = "$Id: string.c,v 1.7 90/08/29 22:24:19 cpcahil Exp $";
#endif
X
int	malloc_checking = 0;
X
char *
strcat(str1,str2)
X	register char	* str1;
X	register char	* str2;
{
X	char		* rtn;
X	int	  len;
X
X	/* 
X	 * check pointers agains malloc region.  The malloc* functions
X	 * will properly handle the case where a pointer does not
X	 * point into malloc space.
X	 */
X	malloc_checking = 1;
X
X	len = strlen(str2);
X	malloc_check_str("strcat", str2);
X
X	len += strlen(str1) + 1;
X	malloc_checking = 0;
X
X	malloc_check_data("strcat", str1, len);
X
X	rtn = str1;
X
X	while( *str1 )
X	{
X		str1++;
X	}
X	
X	while( (*str1 = *str2) != '\0' )
X	{
X		str1++;
X		str2++;
X	}
X	
X	return(rtn);
}
X
char *
strdup(str1)
X	register char	* str1;
{
X	char		* malloc();
X	char		* rtn;
X	register char	* str2;
X
X	malloc_check_str("strdup", str1);
X
X	rtn = str2 = malloc((unsigned)strlen(str1)+1);
X
X	if( rtn != (char *) 0)
X	{
X		while( (*str2 = *str1) != '\0' )
X		{
X			str1++;
X			str2++;
X		}
X	}
X
X	return(rtn);
}
X
char *
strncat(str1,str2,len)
X	register char	* str1;
X	register char	* str2;
X	register int	  len;
{
X	int 		  len1;
X	int 		  len2;
X	char		* rtn;
X
X	malloc_check_strn("strncat", str2, len);
X
X	malloc_checking = 1;
X
X	len2 = strlen(str2) + 1;
X	len1 = strlen(str1);
X
X	malloc_checking = 0;
X
X
X	if( (len+1) < len2 )
X	{
X		len1 += len + 1;
X	}
X	else
X	{
X		len1 += len2;
X	}
X	malloc_check_data("strncat", str1, len1);
X
X	rtn = str1;
X
X	while( *str1 )
X	{
X		str1++;
X	}
X
X	while( len-- && ((*str1++ = *str2++) != '\0') )
X	{
X	}
X	
X	if( ! len )
X	{
X		*str1 = '\0';
X	}
X
X	return(rtn);
}
X
int
strcmp(str1,str2)
X	register char	* str1;
X	register char	* str2;
{
X	malloc_check_str("strcmp", str1);
X	malloc_check_str("strcmp", str2);
X
X	while( *str1 && (*str1 == *str2) )
X	{
X		str1++;
X		str2++;
X	}
X
X
X	/*
X	 * in order to deal with the case of a negative last char of either
X	 * string when the other string has a null
X	 */
X	if( (*str2 == '\0') && (*str1 == '\0') )
X	{
X		return(0);
X	}
X	else if( *str2 == '\0' )
X	{
X		return(1);
X	}
X	else if( *str1 == '\0' )
X	{
X		return(-1);
X	}
X	
X	return( *str1 - *str2 );
}
X
int
strncmp(str1,str2,len)
X	register char	* str1;
X	register char	* str2;
X	register int	  len;
{
X	malloc_check_strn("strncmp", str1, len);
X	malloc_check_strn("strncmp", str2, len);
X
X	while( --len >= 0 && *str1 && (*str1 == *str2) )
X	{
X		str1++;
X		str2++;
X	}
X
X	if( len < 0 )
X	{
X		return(0);
X	}
X	/*
X	 * in order to deal with the case of a negative last char of either
X	 * string when the other string has a null
X	 */
X	if( (*str2 == '\0') && (*str1 == '\0') )
X	{
X		return(0);
X	}
X	else if( *str2 == '\0' )
X	{
X		return(1);
X	}
X	else if( *str1 == '\0' )
X	{
X		return(-1);
X	}
X	
X	return( *str1 - *str2 );
}
X
char *
strcpy(str1,str2)
X	register char	* str1;
X	register char	* str2;
{
X	char		* rtn;
X	int		  len;
X
X	malloc_checking = 1;
X	len = strlen(str2) + 1;
X	malloc_checking = 0;
X
X	malloc_check_data("strcpy", str1, len);
X	malloc_check_data("strcpy", str2, len);
X
X	rtn = str1;
X
X	while( (*str1++ = *str2++) != '\0')
X	{
X	}
X
X	return(rtn);
}
X
char *
strncpy(str1,str2,len)
X	register char	* str1;
X	register char	* str2;
X	register int	  len;
{
X	extern int	  malloc_checking;
X	char		* rtn;
X
X	malloc_check_data("strncpy", str1, len);
X	malloc_check_strn("strncpy", str2, len);
X
X	rtn = str1;
X
X	while((len-- > 0) && (*str1++ = *str2++) != '\0')
X	{
X	}
X	while( (len-- > 0) )
X	{
X		*str1++ = '\0';
X	}
X
X	return(rtn);
}
X
int
strlen(str1)
X	register char	* str1;
{
X	register char	* s;
X
X	if(! malloc_checking )
X	{
X		malloc_check_str("strlen", str1);
X	}
X
X	for( s = str1; *s; s++)
X	{
X	}
X
X	return( s - str1 );
}
X
char *
strchr(str1,c)
X	register char	* str1;
X	register int	  c;
{
X	malloc_check_str("strchr", str1);
X
X	while( *str1 && (*str1 != (char) c) )
X	{
X		str1++;
X	}
X
X	if(*str1 != (char) c)
X	{
X		str1 = (char *) 0;
X	}
X
X	return(str1);
}
X
char *
strrchr(str1,c)
X	register char	* str1;
X	register int	  c;
{
X	register char	* rtn = (char *) 0;
X
X	malloc_check_str("strrchr", str1);
X
X	while( *str1 )
X	{
X		if(*str1 == (char) c )
X		{
X			rtn = str1;
X		}
X		str1++;
X	}
X
X	if( *str1 == (char) c)
X	{
X		rtn = str1;
X	}
X
X	return(rtn);
}
X
char *
index(str1,c)
X	char		* str1;
X	char		  c;
{
X	return( strchr(str1,c) );
}
X
char *
rindex(str1,c)
X	char		* str1;
X	char		  c;
{
X	return( strrchr(str1,c) );
}
X
char *
strpbrk(str1,str2)
X	register char	* str1;
X	register char	* str2;
{
X	register char	* tmp;
X
X	malloc_check_str("strpbrk", str1);
X	malloc_check_str("strpbrk", str2);
X
X	while(*str1)
X	{
X		for( tmp=str2; *tmp && *tmp != *str1; tmp++)
X		{
X		}
X		if( *tmp )
X		{
X			break;
X		}
X		str1++;
X	}
X
X	if( ! *str1 )
X	{
X		str1 = (char *) 0;
X	}
X
X	return(str1);
}
X
int
strspn(str1,str2)
X	register char	* str1;
X	register char	* str2;
{
X	register char	* tmp;
X	char		* orig = str1;
X
X	malloc_check_str("strspn", str1);
X	malloc_check_str("strspn", str2);
X
X	while(*str1)
X	{
X		for( tmp=str2; *tmp && *tmp != *str1; tmp++)
X		{
X		}
X		if(! *tmp )
X		{
X			break;
X		}
X		str1++;
X	}
X
X	return( (int) (str1 - orig) );
}
X
int
strcspn(str1,str2)
X	register char	* str1;
X	register char	* str2;
{
X	register char	* tmp;
X	char		* orig = str1;
X
X	malloc_check_str("strcspn", str1);
X	malloc_check_str("strcspn", str2);
X
X	while(*str1)
X	{
X		for( tmp=str2; *tmp && *tmp != *str1; tmp++)
X		{
X		}
X		if( *tmp )
X		{
X			break;
X		}
X		str1++;
X	}
X
X	return( (int) (str1 - orig) );
}
X
/*
X * strtok() source taken from that posted to comp.lang.c by Chris Torek
X * in Jan 1990.
X */
X
/*
X * Copyright (c) 1989 The Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by the University of California, Berkeley.  The name of the
X * University may not be used to endorse or promote products derived
X * from this software without specific prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X */
X
/*
X * Get next token from string s (NULL on 2nd, 3rd, etc. calls),
X * where tokens are nonempty strings separated by runs of
X * chars from delim.  Writes NULs into s to end tokens.  delim need not
X * remain constant from call to call.
X *
X * Modified by cpc: 	changed variable names to conform with naming
X *			conventions used in rest of code.  Added malloc pointer
X *			check calls.
X */
char *
strtok(str1, str2)
X	char 	* str1;
X	char	* str2;
{
X	static char 	* last;
X	char		* strtoken();
X
X	if( str1 )
X	{
X		malloc_check_str("strtok", str1);
X		last = str1;
X	}
X	malloc_check_str("strtok", str2);
X
X	return (strtoken(&last, str2, 1));
}
X
X
/*
X * Get next token from string *stringp, where tokens are (possibly empty)
X * strings separated by characters from delim.  Tokens are separated
X * by exactly one delimiter iff the skip parameter is false; otherwise
X * they are separated by runs of characters from delim, because we
X * skip over any initial `delim' characters.
X *
X * Writes NULs into the string at *stringp to end tokens.
X * delim will usually, but need not, remain constant from call to call.
X * On return, *stringp points past the last NUL written (if there might
X * be further tokens), or is NULL (if there are definitely no more tokens).
X *
X * If *stringp is NULL, strtoken returns NULL.
X */
char *
strtoken(stringp, delim, skip)
X	register char **stringp;
X	register char *delim;
X	int skip;
{
X	register char *s;
X	register char *spanp;
X	register int c, sc;
X	char *tok;
X
X	if ((s = *stringp) == NULL)
X		return (NULL);
X
X	if (skip) {
X		/*
X		 * Skip (span) leading delimiters (s += strspn(s, delim)).
X		 */
X	cont:
X		c = *s;
X		for (spanp = delim; (sc = *spanp++) != 0;) {
X			if (c == sc) {
X				s++;
X				goto cont;
X			}
X		}
X		if (c == 0) {		/* no token found */
X			*stringp = NULL;
X			return (NULL);
X		}
X	}
X
X	/*
X	 * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
X	 * Note that delim must have one NUL; we stop if we see that, too.
X	 */
X	for (tok = s;;) {
X		c = *s++;
X		spanp = delim;
X		do {
X			if ((sc = *spanp++) == c) {
X				if (c == 0)
X					s = NULL;
X				else
X					s[-1] = 0;
X				*stringp = s;
X				return (tok);
X			}
X		} while (sc != 0);
X	}
X	/* NOTREACHED */
}
X
/*
X * $Log:	string.c,v $
X * Revision 1.7  90/08/29  22:24:19  cpcahil
X * added new function to check on strings up to a specified length 
X * and used it within several strn* functions.
X * 
X * Revision 1.6  90/07/16  20:06:56  cpcahil
X * fixed several minor bugs found with Henry Spencer's string/mem function
X * tester program.
X * 
X * Revision 1.5  90/06/10  14:59:49  cpcahil
X * Fixed a couple of bugs in strncpy & strdup
X * 
X * Revision 1.4  90/05/11  00:13:10  cpcahil
X * added copyright statment
X * 
X * Revision 1.3  90/02/24  21:50:32  cpcahil
X * lots of lint fixes
X * 
X * Revision 1.2  90/02/24  17:29:40  cpcahil
X * changed $Header to $Id so full path wouldnt be included as part of rcs 
X * id string
X * 
X * Revision 1.1  90/02/22  23:17:44  cpcahil
X * Initial revision
X * 
X */
SHAR_EOF
chmod 0640 dmake/dbug/malloc/string.c ||
echo 'restore of dmake/dbug/malloc/string.c failed'
Wc_c="`wc -c < 'dmake/dbug/malloc/string.c'`"
test 9382 -eq "$Wc_c" ||
	echo 'dmake/dbug/malloc/string.c: original size 9382, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= dmake/dbug/malloc/testmem.c ==============
if test -f 'dmake/dbug/malloc/testmem.c' -a X"$1" != X"-c"; then
	echo 'x - skipping dmake/dbug/malloc/testmem.c (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
sed 's/^X//' << 'SHAR_EOF' > 'dmake/dbug/malloc/testmem.c' &&
/* 
X * This stuff is all stolen (with permission, since it was in the public
X * domain) from Henry Spencer's string and memory library.  Thanks Henry.
X */
X
/*
X * Test program for string(3) routines.
X * 
X * Note that at least one Bell Labs implementation of the string
X * routines flunks a couple of these tests -- the ones which test
X * behavior on "negative" characters.
X */
X
#include <stdio.h>
#include <string.h>
X
char * index();
char * rindex();
X
#define	STREQ(a, b)	(strcmp((a), (b)) == 0)
X
char *it = "<UNSET>";		/* Routine name for message routines. */
int waserror = 0;		/* For exit status. */
X
char uctest[] = "\004\203";	/* For testing signedness of chars. */
int charsigned;			/* Result. */
X
/*
X - check - complain if condition is not true
X */
void
check(thing, number)
int thing;
int number;			/* Test number for error message. */
{
X	if (!thing) {
X		printf("%s flunked test %d\n", it, number);
X		waserror = 1;
X	}
}
X
/*
X - equal - complain if first two args don't strcmp as equal
X */
void
equal(a, b, number)
char *a;
char *b;
int number;			/* Test number for error message. */
{
X	check(a != NULL && b != NULL && STREQ(a, b), number);
}
X
char one[50];
char two[50];
X
#ifdef UNIXERR
#define ERR 1
#endif
#ifdef BERKERR
#define ERR 1
#endif
#ifdef ERR
int f;
extern char *sys_errlist[];
extern int sys_nerr;
extern int errno;
#endif
X
/* ARGSUSED */
main(argc, argv)
int argc;
char *argv[];
{
X	/*
X	 * First, establish whether chars are signed.
X	 */
X	if (uctest[0] < uctest[1])
X		charsigned = 0;
X	else
X		charsigned = 1;
X
X	/*
X	 * Then, do the rest of the work.  Split into two functions because
X	 * some compilers get unhappy about a single immense function.
X	 */
X	first();
X	second();
X
X	exit((waserror) ? 1 : 0);
}
X
first()
{
X	/*
X	 * Test strcmp first because we use it to test other things.
X	 */
X	it = "strcmp";
X	check(strcmp("", "") == 0, 1);		/* Trivial case. */
X	check(strcmp("a", "a") == 0, 2);	/* Identity. */
X	check(strcmp("abc", "abc") == 0, 3);	/* Multicharacter. */
X	check(strcmp("abc", "abcd") < 0, 4);	/* Length mismatches. */
X	check(strcmp("abcd", "abc") > 0, 5);
X	check(strcmp("abcd", "abce") < 0, 6);	/* Honest miscompares. */
X	check(strcmp("abce", "abcd") > 0, 7);
X	check(strcmp("a\203", "a") > 0, 8);	/* Tricky if char signed. */
X	if (charsigned)				/* Sign-bit comparison. */
X		check(strcmp("a\203", "a\003") < 0, 9);
X	else
X		check(strcmp("a\203", "a\003") > 0, 9);
X	check(strcmp("a", "a\203") < 0, 10);	/* Tricky if char signed. */
X
X	/*
X	 * Test strcpy next because we need it to set up other tests.
X	 */
X	it = "strcpy";
X	check(strcpy(one, "abcd") == one, 1);	/* Returned value. */
X	equal(one, "abcd", 2);			/* Basic test. */
X
X	(void) strcpy(one, "x");
X	equal(one, "x", 3);			/* Writeover. */
X	equal(one+2, "cd", 4);			/* Wrote too much? */
X
X	(void) strcpy(two, "hi there");
X	(void) strcpy(one, two);
X	equal(one, "hi there", 5);		/* Basic test encore. */
X	equal(two, "hi there", 6);		/* Stomped on source? */
X
X	(void) strcpy(one, "");
X	equal(one, "", 7);			/* Boundary condition. */
X
X	/*
X	 * strcat
X	 */
X	it = "strcat";
X	(void) strcpy(one, "ijk");
X	check(strcat(one, "lmn") == one, 1);	/* Returned value. */
X	equal(one, "ijklmn", 2);		/* Basic test. */
X
X	(void) strcpy(one, "x");
X	(void) strcat(one, "yz");
X	equal(one, "xyz", 3);			/* Writeover. */
X	equal(one+4, "mn", 4);			/* Wrote too much? */
X
X	(void) strcpy(one, "gh");
X	(void) strcpy(two, "ef");
X	(void) strcat(one, two);
X	equal(one, "ghef", 5);			/* Basic test encore. */
X	equal(two, "ef", 6);			/* Stomped on source? */
X
X	(void) strcpy(one, "");
X	(void) strcat(one, "");
X	equal(one, "", 7);			/* Boundary conditions. */
X	(void) strcpy(one, "ab");
X	(void) strcat(one, "");
X	equal(one, "ab", 8);
X	(void) strcpy(one, "");
X	(void) strcat(one, "cd");
X	equal(one, "cd", 9);
X
X	/*
X	 * strncat - first test it as strcat, with big counts, then
X	 * test the count mechanism.
X	 */
X	it = "strncat";
X	(void) strcpy(one, "ijk");
X	check(strncat(one, "lmn", 99) == one, 1);	/* Returned value. */
X	equal(one, "ijklmn", 2);		/* Basic test. */
X
X	(void) strcpy(one, "x");
X	(void) strncat(one, "yz", 99);
X	equal(one, "xyz", 3);			/* Writeover. */
X	equal(one+4, "mn", 4);			/* Wrote too much? */
X
X	(void) strcpy(one, "gh");
X	(void) strcpy(two, "ef");
X	(void) strncat(one, two, 99);
X	equal(one, "ghef", 5);			/* Basic test encore. */
X	equal(two, "ef", 6);			/* Stomped on source? */
X
X	(void) strcpy(one, "");
X	(void) strncat(one, "", 99);
X	equal(one, "", 7);			/* Boundary conditions. */
X	(void) strcpy(one, "ab");
X	(void) strncat(one, "", 99);
X	equal(one, "ab", 8);
X	(void) strcpy(one, "");
X	(void) strncat(one, "cd", 99);
X	equal(one, "cd", 9);
X
X	(void) strcpy(one, "ab");
SHAR_EOF
true || echo 'restore of dmake/dbug/malloc/testmem.c failed'
fi
echo 'End of part 6, continue with part 7'
echo 7 > _shar_seq_.tmp
exit 0

exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.