/*
 * libsal/debug/debug_stacktrace.c
 * Show function-call stack for debugging output
 * 
 * DESCRIPTION
 * 
 * 	sal_dprintf() calls sal_debug_ShowMessgeSuffix() after having
 * 	printed the main message from the process.  
 *	sal_debug_ShowMessageSuffix() in turn calls this routine, to
 * 	see if we should output a copy of the current function call stack.
 * 
 * 	At the time of writing, full support for the function call stack
 * 	is implemented within libsal, but Generic NQS itself does not
 * 	yet make use of it (it's quite a task, going round every single
 * 	routine to add ENTER_FUNCTION and EXIT_FUNCTION calls).  This
 * 	will change over the next month or so.
 * 
 * 	Original Author
 * 	===============
 * 	Stuart Herbert
 * 	Academic Computing Services, The University of Sheffield
 */

#include <libsal/license.h>
#include <libsal/debug/internal.h>
#include <libsal/proto.h>
#include <libsal/defines.h>

/*
 * !! FUNCTION:	sal_debug_ShowStackTrace
 * !! PURPOSE:	Attempt to output a copy of the function stack to the
 * !! PURPOSE:	debugging routine sal_debug_dprintf().  This routine
 * !! PURPOSE:	will silently fail if a stack trace is not required
 * !! PURPOSE:	at the current debugging level.
 * 
 * !! A_NAME:	gMessType
 * !! A_TYPE:	sal_debug_msg_t
 * !! A_DESC:	Which type of debugging message are we doing a stack
 * !! A_DESC:	trace for?
 * 
 * !! NO_RET:
 * !! END_FUNCTION:
 */

void sal_debug_ShowStackTrace(sal_debug_msg_t gMessType)
{
  const sal_debug_func_t	* pstStackEntry;
    /* pointer to entries on the call stack */
  
  /* ensure we're happy with the arguments */
  TEST_ARG(gMessType > SAL_DEBUG_MSG_START, 1);
  TEST_ARG(gMessType < SAL_DEBUG_MSG_END,   1);
  
  /* should we show the function call stack? */
  if (!sal_debug_QueryShowTrace(gMessType))
    return;
  
  /* yes we should.  But do we have a call stack to show? */
  
  /*
   * !! FIXME:	Warning about absence of call stack
   * !! DESC:	When no call stack is present, we silently return
   * !! DESC:	back to the caller.  Should we instead report
   * !! DESC:	a warning?
   * !! END_FIXME:
   */
  
  if ((pstStackEntry = sal_debug_CallStack_Peep(NULL)) == NULL)
    return;
  
  /* yes we do.  Iterate through the stack. */
  
  while (pstStackEntry != NULL)
  {
    sal_debug_dprintf
    (
      gMessType, 
      "Called from %s, in file %s at line %ul\n", 
      pstStackEntry->szFunction, 
      pstStackEntry->szFile, 
      pstStackEntry->ulLine
    );
    pstStackEntry = sal_debug_CallStack_Peep(pstStackEntry);
  }
  
  sal_debug_dprintf(gMessType, "End of call trace\n");
}
