Code Search for Developers
 
 
  

requireImplementation.c from redshed at Krugle


Show requireImplementation.c syntax highlighted

/****************************************************************************************
	requireImplementation.c $Revision: 30 $
		<http://rentzsch.com/require>
	
	Copyright © 1997-2002 Red Shed Software. All rights reserved.
	by Jonathan 'Wolf' Rentzsch (jon at redshed dot net)
	
	************************************************************************************/

#include	"requireDefinitions.h"

/**************************
*	
*	Funky Protos
*	
**************************/
#pragma mark	(Funky Protos)

	void
RequireNotice(
	const	char			*msg,
	const	char			*code,
	const	char			*note,
			long			nmbr,
	const	char			*file,
			long			line,
			long			errn );

	void
MemoryDummy(
	short	value );

	UInt32
RAppendStringToString(
	const	void	*source,
			UInt32	sourceSize,
			void	*target,
			UInt32	targetSize,
			UInt32	maxSize );

	void
RAppendStringToPString(
	const	void		*source,
			UInt32		sourceSize,
			StringPtr	target,
			UInt32		maxSize );

	void
RAppendPStringToPString(
	const	StringPtr	source,
			StringPtr	target,
			UInt32		maxSize );

	void
RAppendCStringToPString(
	const	char		*source,
			StringPtr	target,
			UInt32		maxSize );

	void
RAppendLongToPString(
	long				number,
	StringPtr			to,
	UInt32				maxSize );

	UInt8
RLongToString(
	long				number,
	void				*string,
	UInt32				maxSize );
	
	UInt32
RGetCStringLength(
	const	char		*string );

	char*
RPToCString(
	StringPtr			string );

/****************************************************************************************
*	
*	Interfaces
*	
****************************************************************************************/
#pragma mark	-
#pragma mark	(Interfaces)

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Mon, Jul 21, 1997	Created.
	
	************************************************************************************/

	void
_Require(
	const	char			*code,	//	The code that broke the requirement.
	const	char			*note,	//	Programmer's note (often nil).
	const	char			*file,	//	File that contains the code that broke the requirement.
			long			line )	//	Line of the file of the code that broke the requirement.
{
	RequireNotice( "Require Failed", code, note, 0, file, line, 0 );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Tue, Mar 30, 1999	Created.
	wolf		Sat, Jan 29, 2000	Carbonized.
	wolf		Mon, Jun 12, 2000	Wrapped test for possible deferenced nil pointer
									in a TARGET_API_MAC_CARBON block.
	
	************************************************************************************/

	void
_RequireMacPtr(
	const	void			*ptr,
	const	char			*name,
	const	char			*file,
			long			line )
{
	OSErr	err;
	
	if( ptr ) {
		if( (long) ptr % 4 )
			RequireNotice( "Mac Ptr is misaligned", name, nil, 0, file, line, 0 );
#if	!TARGET_API_MAC_CARBON
		if( ptr == *(void**) 0 )
			RequireNotice( "Mac Ptr is possibly a dereferenced nil ptr", name, nil,
							0, file, line, 0 );
#endif	//	TARGET_API_MAC_CARBON
		if( (long) ptr < 256 )
			RequireNotice( "Mac Ptr is below 256 bytes", name, nil, 0, file, line, 0 );
		
		//	Force a dereference to cause a crash if the ptr is bogus
		MemoryDummy( *(short*) ptr );
		
		//	Call a couple Toolbox routines to make sure the pointer is Toolbox-okay.
#if	TARGET_API_MAC_CARBON
		err = !IsPointerValid( (Ptr) ptr );
		if( err )
			RequireNotice( "IsPointerValid returned false", name, nil, 0, file, line, 0 );
#else	//	TARGET_API_MAC_CARBON
		(void) PtrZone( (Ptr) ptr );
		err = MemError();
		if( err )
			RequireNotice( "PtrZone got an error", name, nil, 0, file, line, err );
#endif	//	TARGET_API_MAC_CARBON
		if( !err ) {
			(void) GetPtrSize( (Ptr) ptr );
			err = MemError();
			if( err )
				RequireNotice( "GetPtrSize got an error", name, nil, 0, file, line, err );
		}
	} else {
		RequireNotice( "Ptr is nil", name, nil, 0, file, line, 0 );
	}
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Mon, Jul 21, 1997	Created.
	wolf		Mon, Jun 12, 2000	Wrapped test for possible deferenced nil pointer
									in a TARGET_API_MAC_CARBON block.
	
	************************************************************************************/

	void
_RequirePtrAlign(
	const	void			*ptr,
	const	char			*name,
			unsigned long	align,
	const	char			*file,
			long			line )
{
	if( ptr ) {
		if( (long) ptr % align )
			RequireNotice( "Ptr is misaligned", name, nil, 0, file, line, 0 );
#if	!TARGET_API_MAC_CARBON
		if( ptr == *(void**) 0 )
			RequireNotice( "Ptr is possibly a dereferenced nil ptr", name, nil,
							0, file, line, 0 );
#endif	//	TARGET_API_MAC_CARBON
		if( (unsigned long) ptr < 256 )
			RequireNotice( "Ptr is below 256 bytes", name, nil, 0, file, line, 0 );
		//	Force a dereference to cause a crash if the ptr is bogus
		MemoryDummy( *(short*) ptr );
	} else {
		RequireNotice( "Ptr is nil", name, nil, 0, file, line, 0 );
	}
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Mon, Jul 21, 1997	Created.
	wolf		Sat, Jan 29, 2000	Carbonized.
	wolf		Mon, Jun 12, 2000	Wrapped test for possible deferenced nil pointer
									in a TARGET_API_MAC_CARBON block.
	
	************************************************************************************/

	void
_RequireHandle(
	const	void			*handle,	//	The handle to test.
	const	char			*name,		//	The name of the handle.
	const	char			*file,		//	The file which contains the handle.
			long			line )		//	The line of the file of the requirement test.
{
	Ptr		ptr;
	OSErr	err;
	
	if( handle ) {
		//	Make sure the handle is a valid pointer.
		if( (long) handle % 4 )
			RequireNotice( "Handle is misaligned", name, nil, 0, file, line, 0 );
#if	!TARGET_API_MAC_CARBON
		if( handle == *(void**) 0 )
			RequireNotice( "Handle is possibly a dereferenced nil ptr", name, nil,
							0, file, line, 0 );
#endif	//	TARGET_API_MAC_CARBON
		if( (long) handle < 256 )
			RequireNotice( "Handle is below 256 bytes", name, nil, 0, file, line, 0 );
		MemoryDummy( *(short*) handle );
		
		//	Now make sure the master pointer is valid. Note an valid empty handle will have
		//	a nil master pointer.
		ptr = *(char**)handle;
		if( (long) ptr % 4 )
			RequireNotice( "Handle's master pointer is misaligned", name, nil, 0, file, line, 0 );
		if( ptr != nil && (long) ptr < 256 )
			RequireNotice( "Handle's master pointer is below 256 bytes", name, nil, 0, file, line, 0 );
		MemoryDummy( *(short*) ptr );
		
		//	Finally, call a couple Toolbox routines to make sure the handle is Toolbox-okay.
#if	TARGET_API_MAC_CARBON
		err = !IsHandleValid( (Handle) handle );
		if( err )
			RequireNotice( "IsHandleValid returned false", name, nil, 0, file, line, 0 );
#else	//	TARGET_API_MAC_CARBON
		(void) HandleZone( (Handle) handle );
		err = MemError();
		if( err )
			RequireNotice( "HandleZone got an error", name, nil, 0, file, line, err );
#endif	//	TARGET_API_MAC_CARBON
		if( !err && ptr != nil ) {
			(void) GetHandleSize( (Handle) handle );
			err = MemError();
			if( err )
				RequireNotice( "GetHandleSize got an error", name, nil, 0, file, line, err );
		}
	} else {
		RequireNotice( "Handle is nil", name, nil, 0, file, line, 0 );
	}
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Mon, May 17, 1999	Created.
	wolf		Sat, Jan 29, 2000	Carbonized.
	wolf		Mon, Jun 12, 2000	Wrapped test for possible deferenced nil pointer
									in a TARGET_API_MAC_CARBON block.
	
	************************************************************************************/

	void
_RequireResHandle(
	const	void			*handle,	//	The resource handle to test.
	const	char			*name,		//	The name of the handle.
	const	char			*file,		//	The file which contains the handle.
			long			line )		//	The line of the file of the requirement test.
{
	Ptr		ptr;
	OSErr	err;
	
	if( handle ) {
		//	Make sure the handle is a valid pointer.
		if( (long) handle % 4 )
			RequireNotice( "Resource Handle is misaligned", name, nil, 0, file, line, 0 );
#if	!TARGET_API_MAC_CARBON
		if( handle == *(void**) 0 )
			RequireNotice( "Resource Handle is possibly a dereferenced nil ptr", name, nil,
							0, file, line, 0 );
#endif	//	TARGET_API_MAC_CARBON
		if( (long) handle < 256 )
			RequireNotice( "Resource Handle is below 256 bytes", name, nil, 0, file, line, 0 );
		MemoryDummy( *(short*) handle );
		
		//	Now make sure the master pointer is valid. Note an valid empty handle will have
		//	a nil master pointer.
		ptr = *(char**)handle;
		if( (long) ptr % 4 )
			RequireNotice( "Resource Handle's master pointer is misaligned", name, nil, 0, file, line, 0 );
		if( ptr != nil && (long) ptr < 256 )
			RequireNotice( "Resource Handle's master pointer is below 256 bytes", name, nil, 0, file, line, 0 );
		MemoryDummy( *(short*) ptr );
		
		//	Finally, call a couple Toolbox routines to make sure the handle is Toolbox-okay.
#if	TARGET_API_MAC_CARBON
		err = !IsHandleValid( (Handle) handle );
		if( err )
			RequireNotice( "IsHandleValid returned false", name, nil, 0, file, line, 0 );
#else	//	TARGET_API_MAC_CARBON
		(void) HandleZone( (Handle) handle );
		err = MemError();
		if( err )
			RequireNotice( "HandleZone got an error", name, nil, 0, file, line, err );
#endif	//	TARGET_API_MAC_CARBON
		if( !err && ptr != nil ) {
			(void) GetHandleSize( (Handle) handle );
			err = MemError();
			if( err )
				RequireNotice( "GetHandleSize got an error", name, nil, 0, file, line, err );
			GetResAttrs( (Handle) handle );
			err = ResError();
			if( err )
				RequireNotice( "GetResAttr got an error", name, nil, 0, file, line, err );
		}
	} else {
		RequireNotice( "Resource Handle is nil", name, nil, 0, file, line, 0 );
	}
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Wed, Aug 26, 1998	Created.
	wolf		Mon, Jun 12, 2000	Wrapped test for possible deferenced nil pointer
									in a TARGET_API_MAC_CARBON block.
	
	************************************************************************************/

	void
_RequirePString(
	const	void	*string,
	const	char	*name,
			long	size,
			long	min,
			long	max,
	const	char	*file,
			long	line )
{
	long	l;
	
	if( string ) {
#if	!TARGET_API_MAC_CARBON
		if( string == *(void**) 0 )
			RequireNotice( "String is possibly a dereferenced nil ptr", name, nil,
							0, file, line, 0 );
#endif	//	TARGET_API_MAC_CARBON
		if( (long) string < 256 )
			RequireNotice( "String is below 256 bytes", name, nil, 0, file, line, 0 );
		MemoryDummy( *(short*) string );
		l = *(unsigned char*) string;
		//	Here we check if the length byte of the pascal string is greater than the
		//	actual allocated size of the string. Example: "unsigned char s[32]" where s[ 0 ]
		//	== 128. This check only works if we get the correct static type of the given
		//	string (Example: "unsigned char s[32]" instead of "void *s").
		if( size != sizeof(void*) && l > size - 1 )
			RequireNotice( "Pascal string length is greater than allocated size", name, nil, size, file, line, 0 );
		if( min && l < min )
			RequireNotice( "String length is less than required", name, nil, min, file, line, 0 );
		if( max && l > max )
			RequireNotice( "String length is greater than required", name, nil, max, file, line, 0 );
	} else {
		RequireNotice( "String is nil", name, nil, 0, file, line, 0 );
	}
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Fri, Feb 25, 2000	Created.
	wolf		Mon, Jun 12, 2000	Wrapped test for possible deferenced nil pointer
									in a TARGET_API_MAC_CARBON block.
	
	************************************************************************************/

	void
_RequireCString(
	const	void	*string,
	const	char	*name,
			long	min,
			long	max,
	const	char	*file,
			long	line )
{
	long	l;
	
	if( string ) {
#if	!TARGET_API_MAC_CARBON
		if( string == *(void**) 0 )
			RequireNotice( "String is possibly a dereferenced nil ptr", name, nil,
							0, file, line, 0 );
#endif	//	TARGET_API_MAC_CARBON
		if( (long) string < 256 )
			RequireNotice( "String is below 256 bytes", name, nil, 0, file, line, 0 );
		MemoryDummy( *(short*) string );
		l = (long) RGetCStringLength( (char*) string );
		if( min && l < min )
			RequireNotice( "String length is less than required", name, nil, min, file, line, 0 );
		if( max && l > max )
			RequireNotice( "String length is greater than required", name, nil, max, file, line, 0 );
	} else {
		RequireNotice( "String is nil", name, nil, 0, file, line, 0 );
	}
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Wed, Sep 9, 1998	Created.
	wolf		Sat, Jul 1, 2000	Added explicit cast from AEDesc's OSType to long.
	
	************************************************************************************/

	void
_RequireAEDesc(
	const	AEDesc	desc,
	const	char	*name,
			Boolean	canBeNull,
	const	char	*file,
			long	line )
{
	if( !canBeNull )
		_RequireHandle( desc.dataHandle, name, file, line );
	switch( desc.descriptorType ) {
		case 'addr':
		case 'aevt':
		case 'alis':
		case 'appa':
		case 'bool':
		case 'comp':
		case 'decm':
		case 'doub':
		case 'dspt':
		case 'enum':
		case 'esrc':
		case 'evcl':
		case 'evid':
		case 'evrc':
		case 'fals':
		case 'fixd':
		case 'from':
		case 'fss ':
		case 'inte':
		case 'keyw':
		case 'kpid':
		case 'ldbl':
		case 'list':
		case 'long':
		case 'magn':
		case 'miss':
		case 'optk':
		case 'prop':
		case 'psn ':
		case 'qdrt':
		case 'reco':
		case 'rtid':
		case 'sect':
		case 'shor':
		case 'sign':
		case 'sing':
		case 'ssid':
		case 'targ':
		case 'TEXT':
		case 'timo':
		case 'tran':
		case 'true':
		case 'type':
		case 'Pntr':
			break;
		case 'null':
			if( !canBeNull )
				RequireNotice( "AEDesc descriptorType is null", name, nil, 0, file, line, 0 );
			break;
		default:
			RequireNotice( "Unknown AEDesc descriptorType", name, nil, (long) desc.descriptorType, file, line, 0 );
	}
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Fri, Apr 16, 1999	Created.
	
	************************************************************************************/

	void
_RequireSwitch(
			long	value,
	const	char	*name,
	const	char	*file,
			long	line )
{
	RequireNotice( "Unknown Switch Selector", name, nil, value, file, line, 0 );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Fri, Feb 18, 2000	Created.
	wolf		Tue, Oct 29, 2002	Added shouldBeEqual support.
	
	************************************************************************************/

	void
_RequireEqual(
			Boolean	shouldBeEqual,
			long	actualValue,
	const	char	*actualName,
			long	expectedValue,
	const	char	*expectedName,
	const	char	*file,
			long	line )
{
	if( (shouldBeEqual && (actualValue != expectedValue))
		|| (!shouldBeEqual && (actualValue == expectedValue)) )
	{
		Str255	msg = "\pUnexpected value (looking for ";
		RAppendCStringToPString( expectedName, msg, sizeof( Str255 ) - 1 );
		RAppendCStringToPString( ")", msg, sizeof( Str255 ) - 1 );
		RequireNotice( RPToCString( msg ), actualName, nil, actualValue, file, line, 0 );
	}
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Sat, Dec 2, 2000	Created.
	
	************************************************************************************/
	
	void
_RequireFSSpec(
	const	void	*specPtr,
	const	char	*name,
	const	char	*file,
			long	line )
{
	const	FSSpec	*spec = (const FSSpec*) specPtr;
	FInfo	info;
	OSErr	err;
	
	if( spec ) {
#if	!TARGET_API_MAC_CARBON
		if( spec == *(void**) 0 )
			RequireNotice( "FSSpec is possibly a dereferenced nil ptr", name, nil, 0,
							file, line, 0 );
#endif	//	TARGET_API_MAC_CARBON
		if( (long) spec < 256 )
			RequireNotice( "FSSpec is below 256 bytes", name, nil, 0, file, line, 0 );
		MemoryDummy( *(short*) spec );
		
		if( spec->name[ 0 ] > 64 )
			RequireNotice( "FSSpec's name length is greater than the maximum possible size", name, nil, spec->name[ 0 ], file, line, 0 );
		if( spec->vRefNum >= 0 )
			RequireNotice( "FSSpec vRefNum is invalid", name, nil, spec->vRefNum, file, line, 0 );
		
		err = FSpGetFInfo( spec, &info );
		if( err )
			RequireNotice( "FSpGetFInfo got an error", name, nil, 0, file, line, err );
	} else {
		RequireNotice( "FSSpec is nil", name, nil, 0, file, line, 0 );
	}
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Sun, Sep 7, 1997	Created.
	
	Exists so the compiler doesn't optimize it away.
	
	************************************************************************************/

				void
MemoryDummy(	short	value )
{
	value++;
}

/****************************************************************************************
*	
*	Standard Strings
*
*	Same code as in StandardStrings.c, prefixed with a "R". This is so require.c can
*	compile stand-alone.
*	
****************************************************************************************/
#pragma mark	-
#pragma mark	(Standard Strings)

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Tue, Nov 11, 1997	Created.
	wolf		Thu, Mar 4, 1999	Added const safety.
									Changed longs to UInt32s.
									Added Requirement.
	wolf		Sat, Jul 1, 2000	Added overflow requirement and explicit cast.
	
	************************************************************************************/

	UInt32						//	<-	target string's new size
RAppendStringToString(
	const	void	*source,
			UInt32	sourceSize,
			void	*target,
			UInt32	targetSize,
			UInt32	maxSize )	//	->	the limit of target's growth, 0 means no limit.
{
	UInt32	spaceLeft = maxSize ? maxSize - targetSize : 0xFFFFFFFF;
	UInt32	transferSize = sourceSize < spaceLeft ? sourceSize : spaceLeft;

	RequireNote( maxSize > sourceSize, "sourceSize can't be greater than maxSize" );
	RequireSInt32( transferSize );
	
	BlockMoveData( source, ((char*)target) + targetSize, (long) transferSize );
	return( targetSize + transferSize );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Tue, Nov 11, 1997	Created.
	wolf		Thu, Mar 4, 1999	Added const safety.
									Changed longs to UInt32s.
									Added Requirements.
	
	************************************************************************************/

	void
RAppendStringToPString(
	const	void		*source,
			UInt32		sourceSize,
			StringPtr	target,
			UInt32		maxSize )
{
	UInt32	newSize = RAppendStringToString( source, sourceSize, target + 1, target[ 0 ],
											maxSize );
	
	RequireUInt8( maxSize );
	RequireUInt8( newSize );
											
	target[ 0 ] = (UInt8) (newSize & 0x000000FF);
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Tue, Nov 11, 1997	Created.
	wolf		Thu, Mar 4, 1999	Added const safety.
									Changed longs to UInt32s.
	
	************************************************************************************/

	void
RAppendPStringToPString(
	const	StringPtr	source,
			StringPtr	target,
			UInt32		maxSize )
{
	RAppendStringToPString( source + 1, source[ 0 ], target, maxSize );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Tue, Nov 11, 1997	Created.
	wolf		Thu, Mar 4, 1999	Added const safety.
									Changed longs to UInt32s.
	
	************************************************************************************/

	void
RAppendCStringToPString(
	const	char		*source,
			StringPtr	target,
			UInt32		maxSize )
{
	RAppendStringToPString( source, RGetCStringLength( source ), target, maxSize );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Sun, Nov 2, 1997	Created.
	wolf		Thu, Mar 4, 1999	Changed longs to UInt32s.
	
	************************************************************************************/

	void
RAppendLongToPString(
	long		number,
	StringPtr	to,
	UInt32		maxSize )
{
	Str63	str;
	str[ 0 ] = RLongToString( number, str + 1, sizeof( Str63 ) );
	RAppendPStringToPString( str, to, maxSize );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Fri, Sep 12, 1997	Created.
	wolf		Thu, Mar 4, 1999	Changed longs to UInt32s.
	wolf		Sat, Jul 1, 2000	Added overflow requirements, now returns an UInt8
									instead of a UInt32.
	
	************************************************************************************/

	UInt8
RLongToString(
	long	number,
	void	*string,
	UInt32	maxSize )
{
	char		*s = (char*) string;
	long		decimal = 1, numberSize = 0, digit;
	
	//	Write a minus sign if the number is negative and make it positive
	if( number < 0 ) {
		*s++ = '-';
		numberSize++;
		number += (-number) + (-number);
	}
	
	//	Figure the number of decimal places in the given number
	if( number >= 10 ) {
		for( digit = number; digit /= 10; decimal *= 10 ) {}
	}
	
	//	Write out the number
	while( maxSize-- && decimal ) {
		digit = (number / decimal);					//	grab one digit
		number -= digit * decimal;					//	remove the digit from the number
		decimal = decimal == 1 ? 0 : decimal / 10;	//	decrement our decimal place
		digit += ( '0' - 0 );						//	convert into ASCII
		RequireSInt8( digit );						//	make sure we don't overflow
		*s++ = (char) digit;						//	place ASCII digit into string
		++numberSize;
	}
	
	RequireUInt8( numberSize );
	return( (UInt8) numberSize );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Fri, Sep 12, 1997	Created.
	wolf		Thu, Mar 4, 1999	Added const safety.
									Changed longs to UInt32s.
	wolf		Sat, Jul 1, 2000	Added explicit cast for return value.
	
	************************************************************************************/

	UInt32
RGetCStringLength(
	const	char	*string )
{
	const	char	*string2 = string;
	
	for( ; *string2; string2++ ) {}
	
	return( (UInt32) (string2 - string) );
}

/****************************************************************************************
	Commenter	Date				Comment
	---------	-----------------	-----------------------------------------------------
	wolf		Fri, Feb 18, 2000	Created.
	
	************************************************************************************/

	char*
RPToCString(
	StringPtr			string )
{
	string[ string[ 0 ] + 1 ] = 0;
	return( (char*) string + 1 );
}



See more files for this project here

redshed

Code for Mac+WebObjects.

Project homepage: http://sourceforge.net/projects/redshed
Programming language(s): C,Java,Objective C
License: other

  requireDefinitions.h
  requireImplementation.c