#include "backtrace.h"

/* fix VC++ ugliness */
#ifdef WIN32
#	define snprintf _snprintf
#endif

/*	make_backtrace() produces a backtrace for the current thread, and puts it
 *	in the buffer 'backtrace_text', up to 'size' characters.
 */
int make_backtrace(char *backtrace_text, size_t size)
{

#ifndef HAS_EXECINFO
	/* if we haven't got execinfo.h, simply make this return failure string */
#ifdef WIN32
	sprintf(backtrace_text, "%.100s:%d: Windows backtrace info\n", __FILE__, __LINE__);
#else
	sprintf(backtrace_text, "%.100s:%d: execinfo.h not included, so no backtrace produced\n", __FILE__, __LINE__);
#endif
	return 0;

#else
	char	temp_buffer[BACKTRACE_BFSZ];			/* buffer to hold one line of backtrace
 */
    char	**backtrace_strings;				/* string table containing whole backtrace */
	int		backtrace_size;						/* number of elements in backtrace */
	int		i;									/* current position within backtrace */
    void	*backtrace_buffer[BACKTRACE_BFSZ];		/* buffer to hold elements of
 backtrace */

	/* get backtrace elements */
	backtrace_size = backtrace(backtrace_buffer, BACKTRACE_BFSZ);

	/* fail if none are returned */
	if ( ! backtrace_size )
	{
		snprintf(backtrace_text, size - 1, "%s:%d: backtrace() failed, so no backtrace produced\n", __FILE__, __LINE__);
		return 0;
	}

	/* add symbolic information in backtrace to make it useful, and store in
 string table */
	backtrace_strings = backtrace_symbols(backtrace_buffer, backtrace_size);

	/* check we actually got some strings */
	if ( ! backtrace_strings )
	{
		snprintf(backtrace_text, size - 1, "%s:%d: insufficient memory for backtrace_symbols()\n", __FILE__, __LINE__);
		return 0;
	}		

	/* store entire backtrace in backtrace_text */
	*backtrace_text = '\0';
    for ( i = 0; i < backtrace_size; i ++ )
	{
		snprintf(temp_buffer, BACKTRACE_BFSZ - 1, "%s\n", backtrace_strings[i]);
		strncat(backtrace_text, temp_buffer, size - 1);
	}

	/* if we get here, then clean up and return success */
	free(backtrace_strings);
	return 1;

#endif
}


/*	The main() and foobar() functions are only included for testing - they are
 *	enabled by "#define BACKTRACE_TESTING" in trace.h.
 */
#ifdef BACKTRACE_TESTING
void foobar(int baz)
{
	char buffer[1024];

//	printf("%d\n", baz);
    make_backtrace(buffer, 1024);
//	printf("%s", buffer);
}

int main(void)
{
	foobar(9);	
	return EXIT_SUCCESS;
}
#endif
