Index: trunk/src/cf_debug.c
===================================================================
--- trunk/src/cf_debug.c	(revision 50)
+++ trunk/src/cf_debug.c	(revision 51)
@@ -7,4 +7,5 @@
 #include "cf_local.h"
 #include "cf_error.h"
+#include "cf_thread.h"
 
 #include <stdlib.h>
@@ -30,4 +31,22 @@
 	 : ((CF_DEBUG_CTX *)__ctx)->fp)
 
+/**
+ * 디버그 컨텍스트
+ * 
+ * @remark change from public to private
+ */
+typedef void *	CF_Debug_Ctx;
+
+/**
+ * 콜스택 데이터
+ * 
+ * @remark change from public to private
+ */
+typedef struct cf_debug_callStack {
+	char	file[NAME_LENGTH + 1];		/**< 파일 이름 */
+	char	function[NAME_LENGTH + 1];	/**< 함수 이름 */
+	int		line;						/**< 라인 넘버 */
+} CF_Debug_CallStack;
+
 typedef struct __cf_debug_callstack__
 {
@@ -36,4 +55,6 @@
 	int		line;
 
+	int		frameIndex;
+
 	struct __cf_debug_callstack__	* caller;
 } S_CF_DEBUG_CALLSTACK, CF_DEBUG_CALLSTACK;
@@ -41,12 +62,15 @@
 typedef struct __cf_debug_ctx__
 {
-	char	file[NAME_LENGTH + 1];
-	char	func[NAME_LENGTH + 1];
-	int		line;
-
-	FILE	* fp;
+	char		file[NAME_LENGTH + 1];
+	char		func[NAME_LENGTH + 1];
+	int			line;
+
+	FILE		* fp;
+	CF_Mutex	mutex;
 
 	CF_DEBUG_CALLSTACK	callstack;
 } S_CF_DEBUG_CTX, CF_DEBUG_CTX;
+
+CF_Debug_Ctx	gDebugSingleCtx = NULL;
 
 static int
@@ -117,20 +141,4 @@
 
 /**
- * 디버그 컨텍스트를 생성
- *
- * @return 성공 시, CF_Debug_Ctx 형태의 컨텍스트; 실패 시, NULL
- * @see CF_DEBUG_CREATE_CTX
- */
-CF_Debug_Ctx
-CF_Debug_CreateCtx (void)
-{
-	CF_DEBUG_CTX * ctx = NULL;
-
-	ctx = (CF_DEBUG_CTX *) calloc (sizeof (CF_DEBUG_CTX), 1);
-
-	return (CF_Debug_Ctx) ctx;
-}
-
-/**
  * 디버그 컨텍스트를 해제
  *
@@ -141,5 +149,5 @@
  * @see CF_DEBUG_DESTROY_CTX
  */
-int
+static int
 CF_Debug_DestroyCtx (CF_Debug_Ctx ctx)
 {
@@ -159,4 +167,7 @@
 	}
 
+	if (context->mutex)
+		CF_Mutex_Destory (&context->mutex);
+
 	free (context);
 
@@ -165,47 +176,35 @@
 
 /**
- * 디버그 컨텍스트에 출력할 파일 디스크립터를 설정
- *
- * @return 성공 시, CF_OK; 실패 시, 오류 코드
- *
- * @param ctx	디버그 컨텍스트
- * @param fd	파일 디스크립터
- *
- * @see CF_File_Open, CF_File_Create
- */
-int
-CF_Debug_SetOutputFD (CF_Debug_Ctx	ctx,
-					  int			fd)
-{
-	int result = 0;
-	int dupfd = 0;
-
-	CF_DEBUG_CTX	* context = (CF_DEBUG_CTX *) ctx;
-	FILE			* fp = NULL;
-
-	CHECK_INVALID_CTX (ctx);
+ * 디버그 컨텍스트를 생성
+ *
+ * @return 성공 시, CF_Debug_Ctx 형태의 컨텍스트; 실패 시, NULL
+ * @see CF_DEBUG_CREATE_CTX
+ */
+static int
+CF_Debug_CreateCtx (CF_Debug_Ctx * ctx)
+{
+	int				result = 0;
+	CF_DEBUG_CTX	* context = NULL;
 
 	TRY
 	{
-		dupfd = dup (fd);
-		if (dupfd < 0)
+		context = (CF_DEBUG_CTX *) calloc (sizeof (CF_DEBUG_CTX), 1);
+		if (context == NULL)
 		{
-			result = -1;
+			result = CF_ERROR_DEBUG_ALLOCATE_CTX;
 			TRY_BREAK;
 		}
 
-		fp = fdopen (dupfd, "a");
-		if (fp == NULL)
+		result = CF_Mutex_Create (&context->mutex);
+		if (result < 0)
 		{
-			close (dupfd);
-			result = -2;
 			TRY_BREAK;
 		}
 
-		context->fp = fp;
+		*ctx = (CF_Debug_Ctx) context;
 	}
 	CATCH_IF (result < 0)
 	{
-		return CF_ERROR_DEBUG_SET_OUTPUT_FD;
+		CF_Debug_DestroyCtx (context);
 	}
 
@@ -280,7 +279,7 @@
 
 /**
- * 컨텍스트를 업데이트하고 디버그 메시지를 출력
- *
- * @return CF_OK 반환
+ * 컨텍스트에 콜스택 푸시
+ *
+ * @return 성공 시, CF_OK; 실패 시, 오류 코드
  *
  * @param ctx	디버그 컨텍스트
@@ -288,96 +287,6 @@
  * @param func	함수 이름
  * @param line	라인 넘버
- * @param fmt	포맷 스트링
- * @param ...	가변 인자
- *
- * @see CF_Debug_Trace
- */
-int
-CF_Debug_Trace (CF_Debug_Ctx	ctx,
-				const char		* file,
-				const char		* func,
-				const int		line,
-				const char		* fmt, ...)
-{
-	va_list			valist;
-	CF_DEBUG_CTX	* context = (CF_DEBUG_CTX *) ctx;
-
-	CHECK_INVALID_CTX (ctx);
-
-	CF_Debug_Local_UpdateCtx (ctx, file, func, line);
-
-	va_start (valist, fmt);
-	CF_Debug_Local_Print (GET_CTX_OSTREAM (context),
-						  context->file,
-						  context->func,
-						  context->line,
-						  fmt, valist);
-	va_end (valist);
-
-	return CF_OK;
-}
-
-/**
- * 컨텍스트를 업데이트하고 바이너리 데이터를 디버그 메시지와 함께 출력
- *
- * @return 성공 시, CF_OK; 실패 시, 오류 코드
- *
- * @param ctx	디버그 컨텍스트
- * @param file	파일 경로
- * @param func	함수 이름
- * @param line	라인 넘버
- * @param bin	바이너리 데이터
- * @param len	바이너리 길이
- * @param fmt	포맷 스트링
- * @param ...	가변 인자
- *
- * @see CF_DEBUG_TRACE_BIN
- */
-int
-CF_Debug_TraceBin (CF_Debug_Ctx			ctx,
-				   const char			* file,
-				   const char			* func,
-				   const int			line,
-				   const unsigned char	* bin,
-				   const int			len,
-				   const char			* fmt, ...)
-{
-	va_list			valist;
-	CF_DEBUG_CTX	* context = (CF_DEBUG_CTX *) ctx;
- 
-	CHECK_INVALID_CTX (ctx);
-
-	CF_Debug_Local_UpdateCtx (ctx, file, func, line);
-
-	va_start (valist, fmt);
-	CF_Debug_Local_Print (GET_CTX_OSTREAM (context),
-						  context->file,
-						  context->func,
-						  context->line,
-						  fmt, valist);
-	va_end (valist);
-
-	CF_Debug_Local_PrintBin (GET_CTX_OSTREAM (context),
-							 context->file,
-							 context->func,
-							 context->line,
-							 bin, len);
-
-	return CF_OK;
-}
-
-/**
- * 컨텍스트에 콜스택 푸시
- *
- * @return 성공 시, CF_OK; 실패 시, 오류 코드
- *
- * @param ctx	디버그 컨텍스트
- * @param file	파일 경로
- * @param func	함수 이름
- * @param line	라인 넘버
- *
- * @see CF_DEBUG_CALLSTACK_PUSH
- */
-int
+ */
+static int
 CF_Debug_CallStackPush (CF_Debug_Ctx	ctx,
 						const char		* file,
@@ -399,4 +308,5 @@
 	push->line = line;
 	push->caller = context->callstack.caller;
+	push->frameIndex = context->callstack.frameIndex + 1;
 	context->callstack.caller = push;
 
@@ -407,5 +317,5 @@
 
 /**
- * 컨텍스트에서 콜스택 팝
+ * 컨텍스트에서 콜스택에서 TOP을 제거하지 않고 가져옴
  *
  * @return 성공 시, CF_OK; 실패 시, 오류 코드
@@ -414,7 +324,38 @@
  * @param callstack	콜스택 정보를 가져올 콜스택 데이터 구조체 포인터
  *
- * @see CF_Debug_CallStackPop, CF_Debug_CallStack
- */
-int
+ * @see CF_Debug_CallStack
+ */
+static int
+CF_Debug_CallStackPeek (CF_Debug_Ctx		ctx,
+						CF_Debug_CallStack	* callstack)
+{
+	CF_DEBUG_CTX		* context = (CF_DEBUG_CTX *) ctx;
+	CF_DEBUG_CALLSTACK	* pop = NULL;
+
+	pop = context->callstack.caller;
+	if (pop == NULL)
+		return CF_ERROR_DEBUG_PEEK_CALLSTACK;
+
+	if (callstack != NULL)
+	{
+		sprintf (callstack->file    , "%s", pop->file);
+		sprintf (callstack->function, "%s", pop->func);
+		callstack->line = pop->line;
+	}
+
+	return CF_OK;
+}
+
+/**
+ * 컨텍스트에서 콜스택 팝
+ *
+ * @return 성공 시, CF_OK; 실패 시, 오류 코드
+ *
+ * @param ctx		디버그 컨텍스트
+ * @param callstack	콜스택 정보를 가져올 콜스택 데이터 구조체 포인터
+ *
+ * @see CF_Debug_CallStack
+ */
+static int
 CF_Debug_CallStackPop (CF_Debug_Ctx			ctx,
 					   CF_Debug_CallStack	* callstack)
@@ -429,10 +370,6 @@
 		return CF_ERROR_DEBUG_POP_CALLSTACK;
 
-	if (callstack != NULL)
-	{
-		sprintf (callstack->file    , "%s", pop->file);
-		sprintf (callstack->function, "%s", pop->func);
-		callstack->line = pop->line;
-	}
+	if (CF_Debug_CallStackPeek (ctx, callstack) < 0)
+		return CF_ERROR_DEBUG_PEEK_CALLSTACK;
 
 	memset (context->file, 0x00, sizeof (context->file));
@@ -454,2 +391,95 @@
 	return CF_OK;
 }
+
+/**
+ * 현재 콜스택을 출력
+ *
+ * @return 성공 시, CF_OK; 실패 시, 오류 코드
+ *
+ * @param fp 출력 할 파일 포인터
+ */
+int
+CF_Debug_PrintCallStack (FILE * fp)
+{
+	int iter = 0;
+
+	CF_DEBUG_CTX		* ctx = gDebugSingleCtx;
+	CF_DEBUG_CALLSTACK	* callstack = NULL;
+
+	if (ctx == NULL)
+		return CF_ERROR_DEBUG_INVALID_CTX;
+
+	callstack = &ctx->callstack;
+
+	do
+	{
+		if (callstack == NULL)
+			break;
+
+		fprintf (fp, "#%04d %s (%s:%d)\n",
+					 iter,
+					 callstack->func,
+					 callstack->file,
+					 callstack->line);
+
+		callstack = callstack->caller;
+	} while (iter++ < ctx->callstack.frameIndex);
+
+	return CF_OK;
+}
+
+/**
+ * 함수 진입을 명시
+ *
+ * @return 성공 시, CF_OK; 실패 시, 오류 코드
+ *
+ * @param file	파일 경로
+ * @param func	함수 이름
+ * @param line	라인 넘버
+ *
+ * @see CF_Debug_LeaveFunction
+ */
+int
+CF_Debug_EnterFunction (const char	* file,
+						const char	* func,
+						const int	line)
+{
+	int				result = 0;
+	CF_DEBUG_CTX	* ctx = NULL;
+
+	if (gDebugSingleCtx == NULL)
+	{
+		result = CF_Debug_CreateCtx (&gDebugSingleCtx);
+		if (result != CF_OK)
+			return result;
+	}
+	ctx = (CF_DEBUG_CTX *)gDebugSingleCtx;
+
+	CF_Mutex_Lock (&ctx->mutex);
+	CF_Debug_CallStackPush (gDebugSingleCtx, file, func, line);
+	CF_Mutex_Unlock (&ctx->mutex);
+
+	return CF_OK;
+}
+
+/**
+ * 함수 종료를 명시
+ *
+ * @return 성공 시, CF_OK; 실패 시, 오류 코드
+ *
+ * @see CF_Debug_EnterFunction
+ */
+int
+CF_Debug_LeaveFunction (void)
+{
+	CF_DEBUG_CTX * ctx = (CF_DEBUG_CTX *)gDebugSingleCtx;
+
+	if (ctx == NULL)
+		return CF_ERROR_DEBUG_INVALID_CTX;
+
+	CF_Mutex_Lock (&ctx->mutex);
+	CF_Debug_CallStackPop (gDebugSingleCtx, NULL);
+	CF_Mutex_Unlock (&ctx->mutex);
+
+	return CF_OK;
+}
