/*** backtrace.c ***/
/* Generate a stack backtrace
 * (c) Paul Field 1995
 * Based closely on code by Tom Hughes
 */

#include <assert.h>
#include <stdio.h>

#include "Desk.BackTrace.h"

#include "Defs.h"



void	Desk_BackTrace_OutputToStdErr( void)
{
Desk_BackTrace_OutputToStreamWithPrefix( stderr, "");
}




void	Desk_BackTrace_OutputToStreamWithPrefix( FILE* stream, const char* prefix)
{
	_kernel_unwindblock frame;
	char	*language;
	
	fprintf( stream, "%sStack-dump:\n", prefix);
	
	Desk_Backtrace_SupportCurrentFrame( &frame);
	
	while ( _kernel_unwind( &frame, &language) > 0)
		{
		
		Desk_function_name_info	*Desk_name_info;
		unsigned int		*Desk_save_code_pointer;
		unsigned int		*Desk_frame_create_instruction;
		unsigned int		*fp;
		unsigned int		Desk_test_words;
		
		fp = (unsigned int*) (frame.fp & PCMask);
		
		if (fp != NULL)	{
			
			Desk_save_code_pointer		= (unsigned *)(*fp & PCMask);
			Desk_frame_create_instruction	= Desk_save_code_pointer - SaveCodePointerOffset;
			
			/* Search backwards from the frame creation instruction looking for a 'name info' word */
			Desk_name_info = (Desk_function_name_info *)(Desk_frame_create_instruction-1);
			
			for (Desk_test_words = NameInfoSearchWordLimit; Desk_name_info->Desk_ff_code != 0xff && Desk_test_words > 0; Desk_test_words--)
				{
				Desk_name_info--;
				}
			
			/* If we found the name info word we can print the name, otherwise the function is anonymous */
			/*
			if (Desk_name_info->Desk_ff_code == 0xff)
			{ fputs((char *)Desk_name_info - Desk_name_info->length, stderr);
			fputc('\n', stderr);
			}
			else
			{ fputs("<anonymous function>\n", stderr);
			}
			*/
			fprintf( stream, "%s%s	(language is %s)\n",
				prefix,
				(Desk_name_info->Desk_ff_code == 0xff) ?
					(char *)Desk_name_info - Desk_name_info->length
					:
					"<anonymous function>",
				(language) ? language : "<unknown language>"
				);
			}
		}
	
	fprintf( stream, "%s\n", prefix);
	}
