\r
\r
\r
+/***********************************************************************\r
+ <<< [Error4_showToPrintf] >>> \r
+************************************************************************/\r
+void Error4_showToPrintf( int err_num )\r
+{\r
+ TCHAR msg[1024];\r
+ #if _UNICODE\r
+ char msg2[1024];\r
+ #endif\r
+\r
+ if ( err_num != 0 ) {\r
+ Error4_getErrStr( err_num, msg, sizeof(msg) );\r
+ #if _UNICODE\r
+ setlocale( LC_ALL, ".OCP" );\r
+ sprintf_s( msg2, sizeof(msg2), "%S", msg );\r
+ printf( "%s\n", msg2 ); // _ftprintf_s \82Å\82Í\93ú\96{\8cê\82ª\8fo\82Ü\82¹\82ñ\r
+ #else\r
+ printf( "%s\n", msg );\r
+ #endif\r
+\r
+ #if ERR2_ENABLE_ERROR_BREAK\r
+ fprintf( out, "\81i\8aJ\94\8eÒ\82Ö\81j\83\81\83C\83\93\8aÖ\90\94\82Å SetBreakErrorID( %d ); \82ð\8cÄ\82Ñ\8fo\82µ\82Ä\82\82¾\82³\82¢\81B\n",\r
+ g_Err2.ErrID );\r
+ #else\r
+#if 0\r
+ if ( err_num == E_FEW_MEMORY || gs.WindowsLastError == ERROR_NOT_ENOUGH_MEMORY ) {\r
+ /* Not show the message for developper */\r
+ }\r
+ else {\r
+ fprintf( out, "\81i\8aJ\94\8eÒ\82Ö\81jERR2_ENABLE_ERROR_BREAK \82ð\92è\8b`\82µ\82Ä\8dÄ\83R\83\93\83p\83C\83\8b\82µ\82Ä\82\82¾\82³\82¢\81B\n" );\r
+ }\r
+#endif\r
+ #endif\r
+ }\r
+ IfErrThenBreak();\r
+}\r
+\r
+\r
+ \r
/*=================================================================*/\r
/* <<< [CRT_plus_2/CRT_plus_2.c] >>> */ \r
/*=================================================================*/\r
\r
\r
/***********************************************************************\r
+ <<< [printf_to_file] >>> \r
+************************************************************************/\r
+\r
+#if USE_PRINTF_MULTI_THREAD\r
+ enum { g_PrintfMultiThreadCountMax = 8 };\r
+ DWORD g_printf_file_tid[ g_PrintfMultiThreadCountMax ];\r
+ bool g_printf_file_clear;\r
+#endif\r
+\r
+TCHAR g_printf_file_path[MAX_PATH];\r
+int g_printf_file_indent;\r
+\r
+static DWORD gs_locked_thread = 0;\r
+\r
+\r
+void printf_lock_init_const( PrintfFileWorkClass* out_Work )\r
+{\r
+ out_Work->File = NULL;\r
+ #if USE_PRINTF_MULTI_THREAD\r
+ out_Work->Mutex = NULL;\r
+ out_Work->ThreadIndex = 0;\r
+ #endif\r
+}\r
+\r
+errnum_t printf_lock( PrintfFileWorkClass* out_Work )\r
+{\r
+ errnum_t e;\r
+ TCHAR* path;\r
+ DWORD tid = GetCurrentThreadId();\r
+ FILE* file = NULL;\r
+#if USE_PRINTF_MULTI_THREAD\r
+ HANDLE mutex = NULL;\r
+ int thread_index = 0;\r
+#endif\r
+\r
+ printf_lock_init_const( out_Work );\r
+\r
+ e= printf_get_path( &path ); IF(e){goto fin;}\r
+\r
+ #if USE_PRINTF_MULTI_THREAD\r
+ mutex = CreateMutex( NULL, TRUE, TEXT("printf_file_mutex") );\r
+ IF ( mutex == NULL ) { e=E_GET_LAST_ERROR; goto fin; }\r
+ if ( gs_locked_thread == tid )\r
+ { DebugBreak(); } /* Re-entrant error */\r
+ /* Call "GetLogOptionPath" and "AppKey_newWritable" */\r
+ gs_locked_thread = tid;\r
+\r
+ if ( ! g_printf_file_clear ) {\r
+ if ( path != NULL ) _tremove( path );\r
+ g_printf_file_clear = true;\r
+ }\r
+ for ( thread_index = 0; thread_index < _countof( g_printf_file_tid ); thread_index += 1 ) {\r
+ if ( g_printf_file_tid[ thread_index ] == 0 || g_printf_file_tid[ thread_index ] == tid )\r
+ { break; }\r
+ }\r
+ g_printf_file_tid[ thread_index ] = tid;\r
+ #endif\r
+\r
+ if ( path[0] == _T('\0') )\r
+ { file = stdout; }\r
+ else {\r
+ errno_t en;\r
+\r
+ en= _tfopen_s( &file, path, _T("a") );\r
+ if(en){ DebugBreak(); }\r
+ }\r
+\r
+fin:\r
+ out_Work->File = file;\r
+ #if USE_PRINTF_MULTI_THREAD\r
+ out_Work->Mutex = mutex;\r
+ out_Work->ThreadIndex = thread_index;\r
+ #endif\r
+ if ( e != 0 ) {\r
+ printf_unlock( out_Work, e );\r
+ }\r
+ return e;\r
+}\r
+\r
+\r
+errnum_t printf_unlock( PrintfFileWorkClass* work, errnum_t e )\r
+{\r
+ FILE* file = work->File;\r
+#if USE_PRINTF_MULTI_THREAD\r
+ HANDLE mutex = work->Mutex;\r
+#endif\r
+\r
+ if ( file != stdout && file != NULL )\r
+ { fclose( file ); }\r
+\r
+ #if USE_PRINTF_MULTI_THREAD\r
+ if ( mutex != NULL ) {\r
+ gs_locked_thread = 0;\r
+ ReleaseMutex( mutex );\r
+ CloseHandle( mutex );\r
+ }\r
+ #endif\r
+\r
+ printf_lock_init_const( work );\r
+\r
+ return e;\r
+}\r
+\r
+\r
+void printf_to_file( const char* format, ... )\r
+{\r
+ enum { num_8_tab = 8 };\r
+\r
+ va_list va;\r
+ errnum_t e;\r
+ int r;\r
+ FILE* file = NULL;\r
+ int thread_index = 0;\r
+\r
+ ErrStackAreaClass err_stack;\r
+ PrintfFileWorkClass work;\r
+\r
+ PushErr( &err_stack );\r
+\r
+ e= printf_lock( &work ); if(e){goto fin;}\r
+\r
+ file = work.File;\r
+ thread_index = work.ThreadIndex;\r
+\r
+\r
+ #if USE_PRINTF_COUNTER\r
+ if ( g_PrintfCounter.Count == 0 ) {\r
+ char* process_ID;\r
+\r
+ #if USE_PRINTF_MULTI_PROCESS\r
+ process_ID = "ProcessID:";\r
+ #else\r
+ process_ID = "";\r
+ #endif\r
+\r
+ fprintf_s( file, "%*s|{%sg_PrintfCounter.BreakIndent:g_PrintfCounter.BreakCount}\n",\r
+ thread_index * num_8_tab + g_printf_file_indent, "", process_ID );\r
+ }\r
+ #endif\r
+\r
+ #if USE_PRINTF_MULTI_THREAD\r
+ fprintf_s( file, "%*s", thread_index * num_8_tab + g_printf_file_indent + 1, "|" );\r
+ #endif\r
+\r
+ #if USE_PRINTF_COUNTER\r
+ {\r
+ char process_ID[ INT_DECIMAL_LENGTH_MAX + 5 ];\r
+\r
+ #if USE_PRINTF_MULTI_PROCESS\r
+ sprintf_s( process_ID, _countof( process_ID ), "%d:", GetCurrentProcessId() );\r
+ #else\r
+ process_ID[0] = '\0';\r
+ #endif\r
+\r
+ g_PrintfCounter.Count ++;\r
+ fprintf_s( file, "{%s%d:%d}", process_ID, thread_index * num_8_tab + g_printf_file_indent,\r
+ g_PrintfCounter.Count );\r
+ }\r
+ #endif\r
+\r
+ va_start( va, format );\r
+ r= vfprintf_s( file, format, va );\r
+ va_end( va );\r
+ IF(r<0){ e=E_ERRNO; goto fin; }\r
+\r
+ e=0;\r
+fin:\r
+ e= printf_unlock( &work, e );\r
+\r
+ IfErrThenBreak();\r
+ PopErr( &err_stack );\r
+ #if USE_PRINTF_COUNTER\r
+ if ( g_PrintfCounter.BreakCount > 0 &&\r
+ g_PrintfCounter.Count >= g_PrintfCounter.BreakCount &&\r
+ thread_index * num_8_tab + g_printf_file_indent == g_PrintfCounter.BreakIndent )\r
+ { DebugBreakR(); }\r
+ #endif\r
+\r
+ return;\r
+}\r
+\r
+\r
+//[printf_file_start]\r
+void printf_file_start( bool IsDelete, int IndentWidth )\r
+{\r
+ g_printf_file_indent = IndentWidth;\r
+\r
+ if ( IsDelete ) {\r
+ int e;\r
+ TCHAR* path;\r
+\r
+ e= printf_get_path( &path ); IF(e)return;\r
+ if ( path != NULL ) _tremove( path );\r
+ }\r
+ #if USE_PRINTF_MULTI_THREAD\r
+ g_printf_file_clear = true;\r
+ #endif\r
+}\r
+\r
+\r
+// [printf_get_path]\r
+int printf_get_path( TCHAR** out_Path )\r
+{\r
+ int e;\r
+ BOOL b;\r
+ TCHAR desktop[MAX_PATH];\r
+\r
+ if ( g_printf_file_path[0] == '\0' ) {\r
+ b= SHGetSpecialFolderPath( NULL, desktop, CSIDL_DESKTOP, FALSE ); IF(!b){goto err_gt;}\r
+ e= StrT_getFullPath( g_printf_file_path, sizeof(g_printf_file_path),\r
+ _T("DebugOut.txt"), desktop ); IF(e){goto err_gt;}\r
+ }\r
+ if ( g_printf_file_path[0] == '*' ) {\r
+ *out_Path = _T("");\r
+ }\r
+ else {\r
+ *out_Path = g_printf_file_path;\r
+ }\r
+ e=0;\r
+fin:\r
+ return e;\r
+\r
+err_gt: e= E_GET_LAST_ERROR; goto fin;\r
+}\r
+\r
+\r
+// [printf_set_path]\r
+int printf_set_path( const TCHAR* Path )\r
+{\r
+ int e;\r
+\r
+ if ( Path[0] == _T('\0') ) {\r
+ g_printf_file_path[0] = _T('*'); \r
+ g_printf_file_path[1] = _T('\0'); \r
+ e = 0;\r
+ }\r
+ else {\r
+ e= StrT_cpy( g_printf_file_path, sizeof(g_printf_file_path), Path );\r
+ IF(e){goto fin;}\r
+ }\r
+fin:\r
+ return e;\r
+}\r
+\r
+\r
+ \r
+/***********************************************************************\r
+ <<< [GetLogOptionPath] >>> \r
+************************************************************************/\r
+TCHAR* GetLogOptionPath()\r
+{\r
+ int e;\r
+ TCHAR* log_path = NULL;\r
+ TCHAR log_opt_path[MAX_PATH];\r
+\r
+ e= GetCommandLineNamed( _T("Log"), false, log_opt_path, sizeof(log_opt_path) );\r
+ //[out] log_opt_path\r
+ if ( e != E_NOT_FOUND_SYMBOL ) { IF(e)goto fin; }\r
+ ClearError();\r
+ if ( !e ) {\r
+ e= printf_set_path( log_opt_path ); IF(e)goto fin;\r
+ }\r
+\r
+ e= printf_get_path( &log_path ); IF(e)goto fin;\r
+\r
+ e=0;\r
+fin:\r
+ if ( e ) { // if error, return default path\r
+ printf_set_path( _T("") );\r
+ printf_get_path( &log_path );\r
+ }\r
+\r
+ return log_path;\r
+}\r
+\r
+\r
+ \r
+/***********************************************************************\r
<<< [vsprintf_r] >>> \r
************************************************************************/\r
errnum_t vsprintf_r( char* s, size_t s_size, const char* format, va_list va )\r