C:\home\SVGCats_src\src\errors.c
1|/*************************************************************************** 2| 1. <<< テスト&デバッグツール (errors) >>> 3| 4|(テストツール) 5|・常時テストするように、チェックコードをプログラムに埋め込んでおきます。 6| (ASSERT コマンド、ERROR コマンド) 7| 8|(デバッグツール) 9|・デバッグの際、変数の値を確認するために、汎用の printf があります。 10| (Errors_printf コマンド) 11|・Errors_printf で確認できないものの状態を確認するために、プログラムを 12| 停止するコマンドがあります。(Errors_break コマンド) 13|・エラーが起きるケースを特定するために、カウンタがあります。 14| (Errors_counter コマンド) 15|・Visual Studio 環境では、Errors_exit の中の exit 関数にブレークポイントを 16| 貼ると、関数のコールスタックを確認することが出来ます。 17| [EXIT_POINT] のキーワードで検索できます。(ASSERT するところと、 18| exit するところの2箇所) 19|・SDV 環境では、_bf にブレークポイントを設定します。 20| もし、設定し忘れて、プログラムが止まったと思ったら ESC を押してく 21| ださい。 22|****************************************************************************/ 23| 24|#include "mixer_precomp.h" /* Auto precompiled header, Look at mixer-... folder */ 25|// #pragma hdrstop ("mixer_precomp") 26| 27|#if defined(_MSC_VER) && ! defined(UNDER_CE) 28| #include <conio.h> 29|#endif 30|#if ( defined(_WIN32) && !defined(FOR_DOS32) ) && !defined(__BORLANDC__) 31| //#include "windows.h" 32|#endif 33| 34|#define STDLIBS_INCLUDE 35|#define STDLIBS_INCLUDE_STDIO_H 36|#define STDLIBS_INCLUDE_STDLIB_H 37|#define STDLIBS_INCLUDE_STRING_H 38|#define STDLIBS_INCLUDE_STDARG_H 39| 40|#if defined(USES_MXP_AUTOINC) 41| #include "errors.ah" /* Auto include header, Look at mixer-... folder */ 42|#endif 43| 44|#if defined(USES_FILEX) && !defined(FOR_WINCE) 45| #include <errno.h> 46|#endif 47| 48|#if defined(__BORLANDC__) && defined(FOR_DOS32) 49| #include <conio.h> 50|#endif 51| 52| 53| 54|#ifdef vsprintf 55|#undef vsprintf 56|int vsprintf( char*, const char*, ... ); 57|#endif 58| 59|char* Errors_printf_imp2( const char* fmt, va_list va ); 60| 61|ERRORS_VERSION( errors, 2 ); 62| 63|#ifdef FOR_32BIT 64| #define Errors_ErrValue 0xEEEEEEEE 65|#else 66| #define Errors_ErrValue 0xEEEE 67|#endif 68| 69|/*-------------------------------------------------------------------------*/ 70|/* 2. <<<< ◆エラー処理ツール >>>> */ 71|/*-------------------------------------------------------------------------*/ 72| 73|int Errors_bStrongExit = false; 74|int Errors_errDupCount = 0; /* エラー処理中のエラーの重複数 */ 75| 76|/*************************************************************************** 77| 2-1. <<< [Errors_error_imp] エラーを発生する >>> 78|【補足】 79|・内部用です。error マクロから呼出されます。 80|【内部補足】 81|・Except2 が無い場合のみ、ASSERT, ASSERT2_0, error, error2_0 から呼び出されます。 82|・COUNT マクロを使用したとき、プロセッサの通過回数が表示されます。 83| ただし、COUNT マクロにプロセッサが一度も通過していないときは表示されません。 84|****************************************************************************/ 85|#ifndef USES_EXCEPT2 86|void Errors_error_imp( const char* file, int line, int code, char* codeStr, 87| char* fmt, ... ) 88|{ 89| static int err_id = 0; 90| va_list va; 91| #ifdef NDEBUG 92| int ret = ERRORS_IGNORE; 93| #else 94| int ret = ERRORS_EXIT; 95| #endif 96| int msg2_headSize; 97| char msg[1024]; 98| char msg2[1024]; 99| 100| #if defined(ERRORS_PRINTF_TO_WINDOW) && defined(FOR_WIN32) 101| Errors_startPool_release(); 102| #endif 103| 104| /* エラーID の作成 */ 105| err_id ++; 106| 107| /* エラーメッセージの作成 */ 108| va_start( va, fmt ); 109| vsprintf( msg, fmt, va ); 110| va_end( va ); 111| 112| if ( Errors_count > 0 ) { 113| sprintf( msg2, "%s(%d) : id = %d, code = %d, %s, (COUNT=%d) ", 114| file, line, err_id, code, codeStr, Errors_count ); 115| } 116| else { 117| sprintf( msg2, "%s(%d) : id = %d, code = %d, %s, ", 118| file, line, err_id, code, codeStr ); 119| } 120| msg2_headSize = strchr( msg2, '\0' ) - msg2; 121| strcpy( msg2 + msg2_headSize, msg ); 122| 123| if ( strlen( msg2 ) > sizeof(msg2) ) { 124| strcpy( msg2 + sizeof(msg2) - 5, "..." ); 125| bf( Errors_ErrValue, 0, (int)__FILE__, __LINE__ ); 126| } 127| 128| #if defined(USES_ARRX) && defined(USES_OFFSET) 129| if ( Errors_MsgPool_isInit( Errors_MsgPool_getGlobl() ) && 130| Errors_Msg_getGlobl()->code != Errors_NoError ) { 131| Errors_MsgPool_add( Errors_MsgPool_getGlobl(), Errors_Msg_getGlobl() ); 132| } 133| #endif 134| Errors_Msg_init( Errors_Msg_getGlobl(), err_id, code, file, line, "%s", msg2 ); 135| Errors_Msg_getGlobl()->orgMsg = Errors_Msg_getGlobl()->msg + msg2_headSize; 136| 137| 138| /* 二重エラーチェック */ 139| Errors_errDupCount++; 140| if ( Errors_errDupCount > 1 ) { 141| #if defined(USES_ARRX) && defined(USES_OFFSET) && defined(USES_MULTASK) 142| if ( Errors_InitChk_getOrder( &Errors_MsgPool_getGlobl()->msgs ) < 0 ) 143| Errors_printf_release( "二重エラーです:%s", msg2 ); 144| else 145| Errors_printf_release( "二重エラーです。catch または finally の中でエラーになっている可能性があります。" ); 146| #else 147| Errors_printf_release( "二重エラーです。catch または finally の中でエラーになっている可能性があります。" ); 148| #endif 149| Errors_printf_release( "%s", msg2 ); 150| Errors_endAllPool_release(); 151| Errors_exit( file, line ); 152| } 153| 154| /* エラーメッセージのヘッダを出力する */ 155| #if !defined(NDEBUG) && !defined(ERRORS_ERROR_REPORT) 156| Errors_printf( "リリース版では、次の詳細情報は表示されません。" ); 157| #endif 158| #if !defined(NDEBUG) || defined(ERRORS_ERROR_REPORT) 159| if ( Errors_appName != NULL ) 160| Errors_printf_release( "Application = %s", Errors_appName ); 161| if ( Errors_appVersion != NULL ) 162| Errors_printf_release( "Version = %s", Errors_appVersion ); 163| #endif 164| 165| /* エラーハンドル関数の呼出し */ 166| if ( Errors_hdl != NULL ) { 167| ret = (*Errors_hdl)( err_id, code, msg2 ); 168| } 169| 170| /* リリース版ではエラーを無視する警告 */ 171| #ifndef NDEBUG 172| if ( Errors_hdl == NULL ) { 173| Errors_printf_release( "[warning] リリース版では、次のエラーが無視されます。" ); 174| } 175| #endif 176| 177| /* プログラムの終了 */ 178| if ( ret == ERRORS_EXIT ) { 179| Errors_exit( file, line ); 180| } 181| 182| /* エラーを無視してプログラムを続行する */ 183| Errors_clearError(); 184|} 185|#endif 186| 187|/*************************************************************************** 188| 2-2. <<< [Errors_errorStdlib] 標準ライブラリの errno のエラーを発生させる >>> 189|【補足】 190|・コメントは、Visual Studio 6.0 のヘルプより引用 191|****************************************************************************/ 192|#if defined(USES_FILEX) && !defined(FOR_WINCE) 193|void Errors_errorStdlib() 194|{ 195| char* s; 196| 197| switch ( errno ) { 198| 199| case ECHILD: 200| s = "errno = ECHILD : 子プロセスが存在しない"; 201| break; 202| 203| case EAGAIN: 204| s = "errno = EAGAIN : これ以上プロセスを生成できない。プロセス スロットが足りないか、" 205| "メモリ不足か、または最大ネスト レベルに達したために、" 206| "新しいプロセスの生成に失敗しました。"; 207| break; 208| 209| case E2BIG: 210| s = "errno = E2BIG : 引数リストが長すぎる"; 211| break; 212| 213| case EACCES: 214| s = "errno = EACCES : アクセスが拒否された。"; 215| /* ファイルのアクセス権の設定により、指定されたアクセスを行えません。 216| このエラーは、ファイルの属性に反した方法でファイル (場合によっては 217| ディレクトリ) にアクセスしようとしたときに起こります。 218| たとえば、開いていないファイルから読み出そうとしたり、 219| 既存の読み出し専用ファイルを書き込み用に開こうとしたり、 220| ファイルの代わりにディレクトリを開こうとすると、このエラーが起きます。 221| MS-DOS オペレーティング システム 3.0 以降では、ロッキングや共有モード違反も 222| EACCES によって示されます。 223| ファイルまたはディレクトリを既存のディレクトリと同じ名前に変更しようとしたり、 224| 空でないディレクトリを削除しようとした場合にも、このエラーが発生します。 225| */ 226| break; 227| 228| case EBADF: 229| s = "不正なファイル番号。"; 230| /* 2 つの原因が考えられます。1) 指定されたファイル 231| ハンドルが有効なファイル ハンドルの値ではないか、開いているファイルを 232| 参照していないとき。2) 読み出し専用で開いているファイルまたはデバイスに 233| 書き込もうとしたとき。 234| */ 235| break; 236| 237| case EDEADLOCK: 238| s = "リソースのデッドロックが発生する可能性がある。"; 239| break; 240| 241| case EDOM: 242| s = "数値演算関数の引数が関数のドメイン外の値である。"; 243| break; 244| 245| case EEXIST: 246| s = "ファイルが存在する。既に存在するファイルを作成しようとしています。"; 247| /* たとえば、_open の呼び出しで _O_CREAT フラグと _O_EXCL フラグを指定したところ、 248| 指定したファイルが存在している場合です。 249| */ 250| break; 251| 252| case EINVAL: 253| s = "不正な引数。たとえば、ファイル ポインタの移動 (fseek の呼び出し) のとき、" 254| "指定した元の位置がファイルの先頭より前にある場合です。"; 255| break; 256| 257| case EMFILE: 258| s = "開いているファイルが多すぎる。空いているファイル ハンドルがないので、ファイルを開けません。"; 259| break; 260| 261| case ENOENT: 262| s = "ファイルまたはディレクトリがない。指定されたファイルまたはディレクトリが" 263| "存在しないか見つかりません。このメッセージは、指定されたファイルが存在しないか、" 264| "パス名の要素が既存のディレクトリを指定していない場合に発生します。"; 265| break; 266| 267| case ENOEXEC: 268| s = "実行ファイルのエラー。実行可能でないか無効な実行可能ファイル形式を" 269| "持つファイルを実行しようとしました。"; 270| break; 271| 272| case ENOMEM: 273| s = "メモリ不足。実行しようとした操作に十分なメモリがありません。"; 274| /* たとえば、子プロセスを実行するためのメモリが不足しているか、または 275| _getcwd の呼び出しで割り当て要求が満たされないと、このメッセージが発生します。"; */ 276| break; 277| 278| case ENOSPC: 279| s = "デバイスの空き領域不足。デバイスに書き込み用の領域が残っていません " 280| "(たとえば、ディスクがいっぱいになった場合)。"; 281| break; 282| 283| case ERANGE: 284| s = "結果が大きすぎる。数値演算関数の引数が大きすぎて、結果の有効桁数の一部" 285| "または全部が失われます。このエラーは、他の関数でも、引数が想定より大きい" 286| "(たとえば、_getcwd の buffer 引数が大きすぎる) 場合に発生します。"; 287| break; 288| 289| case EXDEV: 290| s = "デバイス間リンク。rename 関数を使って、別のデバイスにファイルを移動しようとしました。"; 291| break; 292| 293| ERRORS_SWITCH_DEFAULT_ASSERT; 294| } 295| 296| error2_1( Errors_Err_Errno, "%s", s ); 297|} 298|#endif 299| 300|/*************************************************************************** 301| 2-3. <<< [Errors_clearError] エラーを発生する >>> 302|【補足】 303|・エラーメッセージをエラーが発生していない状態にします。 304|・エラーが発生したら必ず終了するときや例外を発生させるときは、 305| 本マクロを使用する必要はありません。エラーメッセージを参照して 306| エラーが発生しているか確認するスタイルの場合に、エラー復帰が 307| 済んだときに使用します。 308|・プログラムを開始したときも呼び出してください。 309|****************************************************************************/ 310|void Errors_clearError() 311|{ 312| Errors_Msg_init( Errors_Msg_getGlobl(), 0, Errors_NoError, Errors_ns, 0, Errors_ns ); 313| Errors_errDupCount = 0; 314| #if defined(ERRORS_PRINTF_TO_WINDOW) && defined(FOR_WIN32) 315| Errors_clearPool_release(); 316| #endif 317|} 318| 319| 320| 321|/*************************************************************************** 322| 2-4. <<< [Errors_warning_imp] Errors_warning の関数部分 >>> 323|****************************************************************************/ 324|#if !defined(ERRORS_CUT_DEBUG_TOOL) && !defined(NDEBUG) 325|int Errors_nWarning = 0; 326| 327|void Errors_warning_imp( const char* file, int line, const char* fmt, ... ) 328|{ 329| va_list va; 330| char msg[4096]; 331| 332| va_start( va, fmt ); 333| sprintf( msg, fmt, va ); 334| va_end( va ); 335| 336| Errors_nWarning ++; 337| Errors_printf( "[WARNING] id = %d : %s : %s(%d)", 338| Errors_nWarning, msg, file, line ); 339|} 340|#endif 341| 342| 343|/*************************************************************************** 344| 2-5. <<< [Errors_exit] エラー停止 >>> 345|【補足】 346|・内部用です。エラーを発生させるには、error マクロを使ってください。 347|・内部で exit(0xE); を呼び出しています。 348|・本関数または StdX_exit 関数にブレークポイントを貼れば、プログラムが終了する 349| 直前の状態でブレークできます。 350|・C++ のアプリケーションの静的グローバル変数のデストラクタでチェックする場合は、 351| ERRORS_NO_EXIT_CHK を #define してください。 352|【内部補足】 353|・Errors_error 関数と Except2_Sys_throw_imp 関数から呼出されます。 354|****************************************************************************/ 355|bool Errors_bExiting = false; 356|bool Errors_bCalledExitHandler = false; 357| 358|void Errors_exit( const char* file, int line ) 359|{ 360| /* 引数の退避 */ 361| #ifdef FOR_GHS 362| #ifdef FOR_VR 363| __asm("move $21, $4"); 364| __asm("move $22, $5"); 365| #else 366| __asm("mov r6, r21"); 367| __asm("mov r7, r22"); 368| #endif 369| #endif 370| #ifdef FOR_CA732 371| __asm("mov r6, r21"); 372| __asm("mov r7, r22"); 373| #endif 374| #ifdef FOR_GNU 375| __asm("mov $6, $21"); 376| __asm("mov $7, $22"); 377| #endif 378| #ifdef FOR_CODEW 379| asm(mov r6, r21); 380| asm(mov r7, r22); 381| #endif 382| 383| if ( ! Errors_bExiting ) { 384| Errors_bExiting = true; 385| 386| #ifndef ERRORS_NO_EXIT_CHK 387| Errors_chkDefault(); 388| #endif 389| } 390| if ( Errors_exitHandler != NULL ) { 391| if ( Errors_bCalledExitHandler ) { 392| Errors_printLowLevel( "ExitHandler 内でエラーが発生しました。" ); 393| Errors_endAllPool_release(); 394| } 395| else { 396| Errors_bCalledExitHandler = true; 397| Errors_errDupCount = 0; 398| Errors_exitHandler( Errors_paramOfExitHandler ); 399| } 400| } 401| 402| /* プログラム終了 [EXIT_POINT] */ 403| #ifdef FOR_DOS32 404| exit( 0xE ); 405| #endif 406| #ifdef FOR_WIN32 407| exit( 0xE ); 408| #endif 409| #ifdef FOR_WINCE 410| exit( 0xE ); 411| #endif 412| #ifdef FOR_DOS16 413| exit( 0xE ); 414| #endif 415| #ifdef FOR_GHS 416| #ifdef FOR_VR 417| __asm("move $21, $6"); 418| __asm("move $22, $7"); 419| __asm("lui $4, 0xEEEE"); 420| __asm("ori $4, 0xEEEE"); 421| __asm("lui $5, 0x0000"); 422| __asm("ori $5, 0x0004"); 423| __asm("jal exit"); 424| #else 425| __asm("mov r21, r8"); 426| __asm("mov r22, r9"); 427| __asm("mov 0xEEEEEEEE, r6"); 428| __asm("mov 0x00000004, r7"); 429| __asm("jal exit"); 430| #endif 431| #endif 432| #ifdef FOR_CA732 433| __asm("mov r21, r8"); 434| __asm("mov r22, r9"); 435| __asm("mov 0xEEEEEEEE, r6"); 436| __asm("mov 0x00000004, r7"); 437| __asm("jal exit"); 438| #endif 439| #ifdef FOR_GNU 440| __asm("mov $21, $8"); 441| __asm("mov $22, $9"); 442| __asm("mov 0xEEEEEEEE, $6"); 443| __asm("mov 0x00000004, $7"); 444| __asm("jal exit"); 445| #endif 446| #ifdef FOR_CODEW 447| exit(0xE); 448| #endif 449| file, line; /* avoid warning */ 450|} 451| 452| 453| 454|/*************************************************************************** 455| 2-6. <<< [Errors_chkDefault] プログラム終了時のデフォルトのエラーチェック&表示を行う >>> 456|【補足】 457|・Endeavor(Win2000,VC++6?) でコンパイルした場合、メインウィンドウが閉じる 458| 前に(OnOK の最後などで)呼び出してください。参考:Errors_endPool 459|****************************************************************************/ 460|void Errors_chkDefault() 461|{ 462| static int count = 0; 463| count ++; 464| 465| if ( count == 1 ) { 466| bool bOut = false; 467| 468| #if defined(ERRORS_PRINTF_TO_WINDOW) && defined(FOR_WIN32) 469| Errors_startPool_release(); 470| #endif 471| 472| if ( Errors_errDupCount > 0 ) { 473| 474| #if defined(USES_ARRX) && defined(USES_OFFSET) 475| if ( Errors_InitChk_getOrder( &Errors_MsgPool_getGlobl()->msgs ) >= 0 ) { 476| Errors_MsgPool_print( Errors_MsgPool_getGlobl() ); 477| Errors_Msg_print( Errors_Msg_getGlobl() ); 478| bOut = true; 479| } 480| #endif 481| if ( ! bOut ) { 482| Errors_Msg_print( Errors_Msg_getGlobl() ); 483| #ifdef FOR_ENGLISH 484| Errors_printf_release( "[warning] Error messages may be overritten, because Errors_MsgPool didn't initialize." ); 485| #else 486| Errors_printf_release( "[warning] Errors_MsgPool を初期化していないので、" 487| "上記のエラーメッセージは上書きされたか、" 488| "既に対処したエラーである可能性があります。" ); 489| #endif 490| } 491| } 492| 493| #ifndef NDEBUG 494| if ( Errors_nWarning > 0 ) 495| Errors_printf( "[WARNING] warning count = %d", Errors_nWarning ); 496| #endif 497| 498| /* デフォルトのエラーチェックを行い、ログをファイルに出力する */ 499| #if ! defined(ERRORS_CUT_DEBUG_TOOL) && defined(ERRORS_USE_FUNCLOG) 500| Errors_FuncLog_print(); 501| #endif 502| 503| #ifdef USES_BIGSTACK 504| BIGSTACK_CHECK(); 505| #endif 506| ERRORS_FINISHCHK(); 507| 508| /* デフォルト・最終チェックが行われたことを表示する */ 509| #ifndef NDEBUG 510| Errors_printf_release( "Default Final Chk Done." ); 511| #endif 512| 513| /* 終了直前のエラーメッセージ表示 */ 514| if ( Errors_errDupCount > 0 ) { 515| #ifdef FOR_WIN32 516| { 517| char* s = "エラーが発生しました。\r\n" 518| "プログラムに原因(バグ)があると考えられるときは、" 519| "開発者のホームページでバグ情報を参照するか、" 520| "次に表示される詳細情報を eメールで送ってください。"; 521| 522| if ( Errors_appName == NULL ) { 523| MessageBox( (HWND)Errors_parentWnd, s, "Sage Plaisir Open Source Module", 524| MB_OK | MB_ICONERROR ); 525| } 526| else { 527| char msg[1024]; 528| sprintf( msg, "%s で%s", Errors_appName, s ); 529| MessageBox( (HWND)Errors_parentWnd, msg, Errors_appName, 530| MB_OK | MB_ICONERROR ); 531| } 532| #ifdef ERRORS_PRINTF_TO_WINDOW 533| Errors_endAllPool_release(); 534| #endif 535| } 536| #else 537| Errors_printf_release( "EXIT" ); 538| #endif 539| } 540| else { 541| #if defined(ERRORS_PRINTF_TO_WINDOW) && defined(FOR_WIN32) 542| Errors_endAllPool_release(); 543| #endif 544| } 545| } 546|} 547| 548| 549|/*************************************************************************** 550| 2-7. <<< [Errors_setHandler] エラーハンドラを登録する >>> 551|****************************************************************************/ 552|#ifdef USES_EXCEPT2 553|void Errors_setHandler( Errors_Handler hdl ) 554|{ 555| Except2_Sys_setErrorHandler( hdl ); 556|} 557|#endif 558| 559| 560| 561|/*************************************************************************** 562| 2-8. <<< [Errors_stdErrHandler] 標準的なエラーハンドラ >>> 563|【補足】 564|・Errors_setErrorHandler で登録します。 565|****************************************************************************/ 566|int Errors_stdErrHandler( int id, int code, char* msg ) 567|{ 568| #ifndef NDEBUG 569| if ( code == Errors_ASSERT ) 570| Errors_break( 0xEEEE ); /* [EXIT_POINT] */ 571| #endif 572| 573| #ifdef USES_EXCEPT3 574| if ( code != Errors_ASSERT && code != Except3_Err_OutOfTry ) 575| c_throw( Errors_Msg_getGlobl() ); 576| #endif 577| 578|// #ifdef NDEBUG 579| /* 下の2行のうちどちらか */ 580| Errors_printf_release( "%s", msg ); 581| Errors_MsgPool_print( Errors_MsgPool_getGlobl() ); 582|// #endif 583| 584| return ERRORS_EXIT; 585|} 586| 587| 588| 589|/*--------------------------------------------------------------------*/ 590|/* 3. <<<<◆ (Errors_Msg) エラーメッセージ >>>> */ 591|/*--------------------------------------------------------------------*/ 592| 593| 594| 595| 596|/*************************************************************************** 597| 3-1. <<< [Errors_Msg_init] メッセージを作成する >>> 598|****************************************************************************/ 599|void Errors_Msg_init( Errors_Msg* m, int id, int code, const char* file, 600| int line, const char* msg_fmt, ... ) 601|{ 602| va_list va; 603| 604| m->id = id; 605| m->code = code; 606| strcpy( m->file, file ); 607| m->line = line; 608| va_start( va, msg_fmt ); 609| vsprintf( m->msg, msg_fmt, va ); 610| va_end( va ); 611| if ( Errors_count > 0 ) 612| sprintf( strchr( m->msg, '\0' ), "(COUNT=%d)", Errors_count ); 613|} 614| 615| 616|/*************************************************************************** 617| 3-2. <<< [Errors_Msg_print] メッセージをデバッグ表示する >>> 618|****************************************************************************/ 619|void Errors_Msg_print( Errors_Msg* m ) 620|{ 621| #ifdef NDEBUG 622| Errors_printf_release( "%s", m->msg ); 623| #else 624| Errors_printf_release( "[ERROR] %s", m->msg ); 625| #endif 626|} 627| 628| 629| 630|/*************************************************************************** 631| 3-3. <<< [Errors_Msg_initGlobl] タスク唯一の Errors_Msg 型領域を設定する >>> 632|【補足】 633|・マルチタスク環境でも共有しない Errors_Msg 型のグローバル変数の 634| メモリ領域を設定します。初期マルチタスクで呼び出してください。 635|****************************************************************************/ 636|#ifdef USES_MULTASK 637| 638|Errors_Msg* Errors_Msg_globl = NULL; 639| 640|void Errors_Msg_initGlobl( Errors_Msg* msgs, int msgs_size ) 641|{ 642| ASSERT( size >= sizeof( Errors_Msg ) * MulTask_mIdArr ); 643| Errors_Msg_globl = msgs; 644|} 645| 646|#else 647| 648|Errors_Msg Errors_Msg_globl; 649| 650|#endif 651| 652| 653|/*************************************************************************** 654| 3-4. <<< [Errors_Msg_getGlobl] タスク唯一の Errors_Msg 型グローバル変数を返す >>> 655|【補足】 656|・マルチタスク環境でも共有しない Errors_Msg 型のグローバル変数の 657| アドレスを返します。例外を throw するときなどに使用します。 658|****************************************************************************/ 659|#ifdef USES_MULTASK 660| 661|Errors_Msg* Errors_Msg_getGlobl() 662|{ 663| ASSERT( Errors_Msg_globl != NULL ); 664| return &Errors_Msg_globl[MulTask_Sys_getCurIndex()]; 665|} 666| 667|#else 668| 669|Errors_Msg* Errors_Msg_getGlobl() 670|{ 671| return &Errors_Msg_globl; 672|} 673| 674|#endif 675| 676| 677|/*--------------------------------------------------------------------*/ 678|/* 4. <<<<◆ (Errors_MsgPool) エラーメッセージ・プール >>>> */ 679|/*--------------------------------------------------------------------*/ 680| 681|/*************************************************************************** 682| 4-1. <<< [Errors_MsgPool_initGlobl] タスク唯一の Errors_MsgPool 型領域を設定する >>> 683|【補足】 684|・マルチタスク環境でも共有しない Errors_MsgPool 型のグローバル変数の 685| メモリ領域を設定します。初期マルチタスクで呼び出してください。 686|****************************************************************************/ 687|#ifdef USES_ARRX 688|#ifdef USES_OFFSET 689|#ifdef USES_MULTASK 690| 691|Errors_MsgPool* Errors_MsgPool_globl = NULL; 692| 693|void Errors_MsgPool_initGlobl( Errors_MsgPool* sts, int sts_size ) 694|{ 695| ASSERT( sts_size >= sizeof( Errors_MsgPool ) * MulTask_mIdArr ); 696| Errors_MsgPool_globl = msgs; 697|} 698| 699|#else 700| 701|Errors_MsgPool Errors_MsgPool_globl; 702| 703|#endif 704|#endif 705|#endif 706| 707|/*************************************************************************** 708| 4-2. <<< [Errors_MsgPool_isInit] Errors_MsgPool が初期化されているかを返す >>> 709|****************************************************************************/ 710|#if defined(USES_ARRX) && defined(USES_OFFSET) 711| 712|bool Errors_MsgPool_isInit( Errors_MsgPool* m ) 713|{ 714| return m->msgs.arr.first != NULL; 715|} 716| 717|#endif 718| 719|/*************************************************************************** 720| 4-3. <<< [Errors_MsgPool_getGlobl] タスク唯一の Errors_MsgPool 型グローバル変数を返す >>> 721|【補足】 722|・マルチタスク環境でも共有しない Errors_MsgPool 型のグローバル変数の 723| アドレスを返します。 724|****************************************************************************/ 725|#ifdef USES_ARRX 726|#ifdef USES_OFFSET 727|#ifdef USES_MULTASK 728| 729|Errors_MsgPool* Errors_MsgPool_getGlobl() 730|{ 731| ASSERT( Errors_MsgPool_globl != NULL ); 732| if ( Errors_MsgPool_globl == NULL ) 733| return &Errors_MsgPool_globl; 734| 735| return &Errors_MsgPool_globl[MulTask_Sys_getCurIndex()]; 736|} 737| 738|#else 739| 740|Errors_MsgPool* Errors_MsgPool_getGlobl() 741|{ 742| return &Errors_MsgPool_globl; 743|} 744| 745|#endif 746|#endif 747|#endif 748| 749| 750|/*************************************************************************** 751| 4-4. <<< [Errors_MsgPool_print] 登録されているエラーメッセージをすべて表示する >>> 752|****************************************************************************/ 753|#ifdef USES_ARRX 754|#ifdef USES_OFFSET 755|void Errors_MsgPool_print( Errors_MsgPool* m ) 756|{ 757| int i = 1; 758| Errors_Msg* msg; 759| 760| for ( Errors_MsgPool_forEach( m, &msg ) ) { 761| #ifdef NDEBUG 762| Errors_printf_release( "%s", msg->msg ); 763| #else 764| Errors_printf_release( "[ERROR] %s", msg->msg ); 765| #endif 766| i++; 767| } 768|} 769|#endif 770|#endif 771| 772| 773|/*************************************************************************** 774| 4-5. <<< [Errors_MsgPool_printLowLevel] 登録されているエラーメッセージをすべて表示する >>> 775|****************************************************************************/ 776|#ifdef USES_ARRX 777|#ifdef USES_OFFSET 778|void Errors_MsgPool_printLowLevel( Errors_MsgPool* m ) 779|{ 780| int i = 1; 781| Errors_Msg* msg; 782| char s[4096]; 783| 784| for ( Errors_MsgPool_forEach( m, &msg ) ) { 785| #ifdef NDEBUG 786| sprintf( s, "%s", msg->msg ); 787| #else 788| sprintf( s, "[ERROR] %s", msg->msg ); 789| #endif 790| Errors_printLowLevel( s ); 791| i++; 792| } 793|} 794|#endif 795|#endif 796| 797| 798|/*--------------------------------------------------------------------*/ 799|/* 5. <<<<◆ テストツール >>>> */ 800|/*--------------------------------------------------------------------*/ 801| 802|char* Errors_NorSupport_msg = "Not Support in this Version"; 803|char* Errors_NorSupport_msgFmt = "%s in %s(%d)"; 804|char* Errors_ChkRet_msg = "return error code = %d"; 805| 806|/* テストプログラム用 */ 807|char* Errors_okLabel = "OK."; 808|char* Errors_errLabel = "### ERROR EXIST!! ###"; 809|int Errors_errCount = 0; /* エラーのカウント */ 810| 811|#ifndef USES_EXCEPT2 812| Errors_Handler Errors_hdl = NULL; /* エラーハンドラのアドレス */ 813|#endif 814| 815|Errors_ExitHandler Errors_exitHandler = NULL; 816|void* Errors_paramOfExitHandler; 817| 818| 819|/************************************************************************** 820| 5-1. <<< [Errors_checkSum] チェックサムをかける >>> 821|【引数】 822| ・void** ranges; チェックするメモリの開始アドレスと終了の次のアドレスの配列 823| ・int ranges_size; ranges のメモリサイズ 824|【補足】 825|・プログラム領域や定数データ領域にチェックサムをかけて、プログラム(別タスク 826| のプログラム)によって不正なメモリ領域に書きこみアクセスしていないかを 827| チェックします。(読みこみはこの方法ではチェックできません) 828|・ranges 引数の配列は、次のように格納します。 829| void* ranges[] = { 830| (void*)0x00001000, (void*)0x0x00010000, // 範囲1、開始と終了 831| (void*)0x00021000, (void*)0x0x00030000, // 範囲2、開始と終了 832| }; 833| 終了アドレスのデータはチェックサムにかからないので注意してください。 834| 再コンパイルしてメモリマップが変わる可能性があることに注意してください。 835|・チェックサムに引っかかったら、エラーになります。 836| エラーメッセージには、正しいチェックサムの値が記述されています。 837| (設定によっては、参照するのにデバッグツールが必要です) 838|・定数を変えて再コンパイルすると、プログラムのチェックサムが変わるので、 839| デバッガ上で正しいチェックサムの値を格納するグローバル変数 Errors_sum 840| を設定してください。 841|・チェックサムが引っかかった場所を特定するには、デバッガでそのメモリ領域 842| 全体を比較して行います。ただし、その際、メモリダンプをファイルに落とす 843| 必要が起きるかも知れません。 844|・チェックサムは、メモリ領域を unsigned char の配列と見て、int 型の 845| 合計値に加算して計算しています。ただし、合計値の初期値は 0です。 846|***************************************************************************/ 847|int Errors_sum; /* 正しいチェックサムの値 */ 848| 849|void Errors_checkSum( void** ranges, int ranges_size ) 850|{ 851| int sum = 0; 852| void** ranges_over = (void**)( (char*)ranges + ranges_size ); 853| 854| while ( ranges < ranges_over ) { 855| 856| unsigned char* s; 857| unsigned char* e; 858| 859| s = (unsigned char*)*ranges; ranges++; 860| e = (unsigned char*)*ranges; ranges++; 861| for ( ; s < e; s++ ) sum += (int)*s; 862| } 863| 864| if ( sum != Errors_sum ) { 865| #if (((0))) 866| Errors_printf( 867| "CheckSum ERROR run_sum = %d(0x%08X), right_sum = %d(0x%08X)", 868| sum, sum, Errors_sum, Errors_sum ); 869| #endif 870| error2_4( Errors_BadCheckSum, 871| "CheckSum ERROR run_sum = %d(0x%08X), right_sum = %d(0x%08X)", 872| sum, sum, Errors_sum, Errors_sum ); 873| } 874|} 875| 876| 877|/********************************************************************** 878| 5-2. <<< [Errors_InitChk_imp] 初期化チェックの実装 >>> 879|【補足】 880|・ERRORS_INITCHK の実装部です。 881|・マジックナンバーをチェックして、初期化しているかどうか判定します。 882|・bCountUp は、同じ order のとき、内部でカウントするかどうかです。 883|【内部補足】 884|・チェックは、ERRORS_INITCHK_MAGIC マクロによって暗号化された値が 885| 正しいかどうかによって行います。 886|**********************************************************************/ 887|#ifndef NDEBUG 888|void Errors_InitChk_imp( void* parent, Errors_InitChk* m, 889| int order, const char* file, int line, bool bCountUp ) 890|{ 891| ASSERT( parent != NULL ); 892| 893| /* 初期化関数で行うチェック */ 894| if ( order == 0 ) { 895| m->key = line; 896| m->order = 0; 897| m->count = 1; 898| } 899| 900| /* 一般の関数で行うチェック */ 901| else { 902| if ( m->var != ERRORS_INITCHK_CANCELER_NUM ) { 903| 904| /* マジックナンバーのチェック */ 905| #ifndef NDEBUG 906| if ( m->var != 907| ERRORS_INITCHK_MAGIC( m, m->order, m->key, m->count ) ) { 908| error2_2( Errors_InitMiss, 909| "ERROR in %s(%d) : no init or out of scope", file, line ); 910| } 911| #endif 912| 913| /* 手続きオーダーのチェック */ 914| #ifndef NDEBUG 915| if ( order > m->order + m->count ) { 916| error2_4( Errors_OrderMiss, 917| "ERROR in %s(%d) : func order mistake\r\n" 918| "Current Order = %d ( count %d )", 919| file, line, m->order, m->count ); 920| } 921| #endif 922| } 923| 924| if ( order == m->order ) { 925| if ( bCountUp ) 926| m->count ++; 927| } 928| else if ( order > m->order ) { 929| m->order = order; 930| m->count = 1; 931| } 932| } 933| 934| /* マジックナンバーを作る */ 935| m->var = ERRORS_INITCHK_MAGIC( m, m->order, m->key, m->count ); 936|} 937|#endif /* not NDEBUG */ 938| 939| 940| 941|/********************************************************************** 942| 5-3. <<< [Errors_InitChk_print_imp] 初期化チェックのデバッグ表示の実装 >>> 943|**********************************************************************/ 944|#ifndef ERRORS_CUT_DEBUG_TOOL 945|void Errors_InitChk_print_imp( Errors_InitChk* m, int order ) 946|{ 947| Errors_printf( "&__initchk = %p, var = %08X, now-magic = %08X, culc-magic = %08X", 948| m, m->var, 949| ERRORS_INITCHK_MAGIC( m, order, m->key, m->count ), 950| ERRORS_INITCHK_MAGIC( m, m->order, m->key, m->count ) ); 951|} 952|#endif 953| 954| 955| 956|/*************************************************************************** 957| 5-4. <<< [Errors_FinishChk_count] 後始末カウンタを変更する >>> 958| 5-5. <<< [後始末カウンタ] >>> 959|【引数】 960| ・char* name; 後始末関数名 961| ・int plus; 後始末カウンタを変更する増減分 962|【補足】 963|・後始末カウンタは、オブジェクトを生成したときに−1して、破壊したときに 964| +1するカウンタです。 965|****************************************************************************/ 966|#ifdef USES_ARRX 967|#ifdef USES_OFFSET 968|#ifndef ERRORS_CUT_DEBUG_TOOL 969| 970|ArrX_Buf Errors_Fin_buf = { NULL, NULL, NULL }; 971|Errors_FinElem Errors_Fin_bufX[ERRORS_FINISHCHK_MCLASS*2]; 972|Offset_Key Errors_Fin_key; 973| 974|bool Errors_FinishChk_bInit = false; 975|ArrX_Able Errors_FinishChk_ptrs; 976|ArrX_AbleElemP Errors_FinishChk_ptrsX[ERRORS_FINISHCHK_INSPECT_MOBJ]; 977| 978| 979|void Errors_FinishChk_count( void (*_finish)(), char* name, int plus ) 980|{ 981| int fin = (int)_finish; 982| Errors_FinElem* elem; 983| 984| /* 初めての場合、Errors_Fin_buf を初期化する */ 985| if ( Errors_Fin_buf.first == NULL ) { 986| ArrX_Buf_init( &Errors_Fin_buf, 987| Errors_Fin_bufX, sizeof(Errors_Fin_bufX) ); 988| Offset_Key_init( &Errors_Fin_key, 989| Errors_FinElem, funcAdr, Offset_Int, Offset_NoDirec ); 990| } 991| 992| /* 後始末関数のアドレスに対応する要素を検索する */ 993| elem = ArrX_Buf_search_i( &Errors_Fin_buf, &Errors_Fin_key, 994| fin, Errors_FinElem ); 995| if ( elem == NULL ) { 996| elem = ArrX_Buf_alloc( &Errors_Fin_buf, Errors_FinElem ); 997| strncpy( elem->name, name, ERRORS_FINISHCHK_MNAME ); 998| elem->name[ERRORS_FINISHCHK_MNAME-1] = '\0'; 999| elem->funcAdr = fin; 1000| } 1001| 1002| /* 後始末カウンタを変更する */ 1003| elem->count += plus; 1004|} 1005| 1006|#endif /* not NDEBUG */ 1007|#endif /* USES_OFFSET */ 1008|#endif /* USES_ARRX */ 1009| 1010| 1011| 1012|/*************************************************************************** 1013| 5-6. <<< [Errors_FinishChk_imp] すべてのオブジェクトが後始末されたかチェックする >>> 1014|【補足】 1015|・チェックに引っかかっても error 関数を呼び出しません。 1016|****************************************************************************/ 1017|#ifdef USES_ARRX 1018|#ifdef USES_OFFSET 1019|#ifndef NDEBUG 1020| 1021|void Errors_FinishChk_imp(void) 1022|{ 1023| static int count = 0; 1024| Errors_FinElem* elem; 1025| ArrX_AbleElemP* p; 1026| 1027| count++; 1028| if ( count >= 2 && Errors_bExiting ) { 1029| Errors_printf_release( "デストラクタで FINISHCHK するときは、" 1030| "#define ERRORS_NO_EXIT_CHK を設定してください。" ); 1031| } 1032| 1033| /* 後始末チェック */ 1034| for ( ArrX_Buf_forEach( &Errors_Fin_buf, &elem, Errors_FinElem ) ) { 1035| if ( elem->count != 0 ) { 1036| Errors_printf_release( "%s の後始末カウンタ= %+d", 1037| elem->name, elem->count ); 1038| } 1039| } 1040| 1041| /* 後始末していないオブジェクトのアドレスを表示する */ 1042| if ( Errors_FinishChk_bInit && ArrX_Able_getN( &Errors_FinishChk_ptrs, ArrX_AbleElemP ) > 0 ) { 1043| Errors_printf( "次のアドレスのオブジェクトは、まだ後始末されていません" ); 1044| Errors_printf( "Errors_FinishChk_addr マクロに指定し、" 1045| " Errors_FinishChk_Inspect_forInit_imp 関数内にブレークポイントを張ってください。" ); 1046| for ( ArrX_Able_forEach( &Errors_FinishChk_ptrs, &p, ArrX_AbleElemP ) ) { 1047| Errors_printf( "0x%08X", p->p ); 1048| } 1049| } 1050| 1051| /* StdPlus_chkFree のチェック */ 1052| #ifdef USES_STDPLUS 1053| StdPlus_chkFree(); 1054| #endif 1055| 1056| /* チェックが行われたことを表示する */ 1057| Errors_printf_release( "Finish Chk Done." ); 1058|} 1059| 1060|#endif /* not NDEBUG */ 1061|#endif /* USES_OFFSET */ 1062|#endif /* USES_ARRX */ 1063| 1064| 1065|/*************************************************************************** 1066| 5-7. <<< [Errors_FinishChk_print_imp] 指定の後始末カウンタを表示する >>> 1067|****************************************************************************/ 1068|#ifdef USES_ARRX 1069|#ifdef USES_OFFSET 1070|#ifndef NDEBUG 1071|#ifndef ERRORS_CUT_DEBUG_TOOL 1072| 1073|void Errors_FinishChk_print_imp( const char* _finish, char* file, int line ) 1074|{ 1075| Errors_FinElem* elem; 1076| bool bDisp = false; 1077| 1078| /* 後始末カウンタを表示する */ 1079| for ( ArrX_Buf_forEach( &Errors_Fin_buf, &elem, Errors_FinElem ) ) { 1080| if ( strncmp( elem->name, _finish, ERRORS_FINISHCHK_MNAME - 1 ) == 0 ) { 1081| Errors_printf( "後始末カウンタ %s (%+d) in %s(%d)", 1082| elem->name, elem->count, file, line ); 1083| bDisp = true; break; 1084| } 1085| } 1086| if ( ! bDisp ) { 1087| Errors_printf( "後始末カウンタ %s (%+d) in %s(%d) (It has not inited yet)", 1088| _finish, elem->count, file, line ); 1089| } 1090|} 1091| 1092|#endif /* not ERRORS_CUT_DEBUG_TOOL */ 1093|#endif /* not NDEBUG */ 1094|#endif /* USES_OFFSET */ 1095|#endif /* USES_ARRX */ 1096| 1097| 1098|/*************************************************************************** 1099| 5-8. <<< [Errors_FinishChk_printAll] すべての後始末カウンタを表示する >>> 1100|****************************************************************************/ 1101|#ifdef USES_ARRX 1102|#ifdef USES_OFFSET 1103|#ifndef NDEBUG 1104|#ifndef ERRORS_CUT_DEBUG_TOOL 1105| 1106|void Errors_FinishChk_printAll(void) 1107|{ 1108| Errors_FinElem* elem; 1109| 1110| Errors_printf( "後始末カウンタ一覧 :" ); 1111| for ( ArrX_Buf_forEach( &Errors_Fin_buf, &elem, Errors_FinElem ) ) { 1112| Errors_printf( "%s (%+d)", elem->name, elem->count ); 1113| } 1114|} 1115| 1116|#endif /* not ERRORS_CUT_DEBUG_TOOL */ 1117|#endif /* not NDEBUG */ 1118|#endif /* USES_OFFSET */ 1119|#endif /* USES_ARRX */ 1120| 1121| 1122|/*************************************************************************** 1123| 5-9. <<< [Errors_FinishChk_Inspect_forInit_imp] 後始末を忘れたオブジェクトを調査する >>> 1124|****************************************************************************/ 1125|#if defined(USES_ARRX) && defined(USES_OFFSET) && !defined(ERRORS_CUT_DEBUG_TOOL) 1126| 1127|#define Errors_FinishChk_addr 0x00000000 1128| 1129|void Errors_FinishChk_Inspect_forInit_imp( void* obj, void (*_finish)(), 1130| const char* name ) 1131|{ 1132| ArrX_AbleElemP* p; 1133| 1134| if ( obj == (void*)Errors_FinishChk_addr ) { 1135| MARK(); 1136| } 1137| 1138| /* オブジェクト・ストアを初期化する */ 1139| if ( ! Errors_FinishChk_bInit ) { 1140| ArrX_Able_init( &Errors_FinishChk_ptrs, Errors_FinishChk_ptrsX, 1141| sizeof(Errors_FinishChk_ptrsX), ArrX_AbleElemP ); 1142| Errors_FinishChk_bInit = true; 1143| } 1144| 1145| /* 二重初期化チェック */ 1146| for ( ArrX_Able_forEach( &Errors_FinishChk_ptrs, &p, ArrX_AbleElemP ) ) { 1147| if ( p->p == obj ) 1148| break; 1149| } 1150| if ( p != ArrX_Able_getOver( &Errors_FinishChk_ptrs ) ) { 1151| 1152| p = ArrX_Able_getFirstDisabled( &Errors_FinishChk_ptrs, ArrX_AbleElemP ); 1153| p->p = obj; 1154| ArrX_AbleElem_setAble( p, true ); 1155| 1156| error2_1( Errors_Err_DoubleInit, "二重初期化、または開放し忘れ (addr = %p)", obj ); 1157| } 1158| 1159| /* オブジェクトを登録する */ 1160| p = ArrX_Able_getFirstDisabled( &Errors_FinishChk_ptrs, ArrX_AbleElemP ); 1161| p->p = obj; 1162| ArrX_AbleElem_setAble( p, true ); 1163| 1164| 1165| /* 後始末カウンタとの整合性をチェックする */ 1166| #if 0 1167| { 1168| Errors_FinElem* elem; 1169| int fin = (int)_finish; 1170| 1171| elem = ArrX_Buf_search_i( &Errors_Fin_buf, &Errors_Fin_key, 1172| fin, Errors_FinElem ); 1173| if ( elem == NULL ) { 1174| elem = ArrX_Buf_alloc( &Errors_Fin_buf, Errors_FinElem ); 1175| strncpy( elem->name, name, ERRORS_FINISHCHK_MNAME ); 1176| elem->name[ERRORS_FINISHCHK_MNAME-1] = '\0'; 1177| elem->funcAdr = fin; 1178| } 1179| if ( elem->count != ArrX_Able_getN( &Errors_FinishChk_ptrs, ArrX_AbleElemP ) ) { 1180| Errors_printf( "FinishChk count1 = %d, count2 = %d", 1181| elem->count, ArrX_Able_getN( &Errors_FinishChk_ptrs, ArrX_AbleElemP ) ); 1182| Errors_break( 0x4141 ); 1183| } 1184| } 1185| #else 1186| name, _finish; /* avoid warning */ 1187| #endif 1188|} 1189|#endif 1190| 1191| 1192|/*************************************************************************** 1193| 5-10. <<< [Errors_FinishChk_Inspect_forFinish_imp] 後始末を忘れたオブジェクトを調査する >>> 1194|****************************************************************************/ 1195|#if defined(USES_ARRX) && defined(USES_OFFSET) && !defined(ERRORS_CUT_DEBUG_TOOL) 1196| 1197|void Errors_FinishChk_Inspect_forFinish_imp( void* obj, void (*_finish)(), 1198| const char* name ) 1199|{ 1200| ArrX_AbleElemP* p = (ArrX_AbleElemP*)ArrX_Able_getOver( &Errors_FinishChk_ptrs ); 1201| 1202| if ( obj == (void*)Errors_FinishChk_addr ) { 1203| MARK(); 1204| } 1205| 1206| /* オブジェクトを登録からはずす */ 1207| for ( ArrX_Able_forEach( &Errors_FinishChk_ptrs, &p, ArrX_AbleElemP ) ) { 1208| if ( p->p == obj ) { 1209| ArrX_AbleElem_setAble( p, false ); 1210| break; 1211| } 1212| } 1213| 1214| /* 二重後始末チェック */ 1215| if ( p == ArrX_Able_getOver( &Errors_FinishChk_ptrs ) ) { 1216| error2_1( Errors_Err_NoInit, "初期化関数に ERRORS_FINISHCHK_INSPECT_FOR_INIT " 1217| "が抜けているか、2重開放か、無効なアドレスです。 (addr = %p)", obj ); 1218| } 1219| 1220| /* 後始末カウンタとの整合性をチェックする */ 1221| #if 0 1222| { 1223| Errors_FinElem* elem; 1224| int fin = (int)_finish; 1225| 1226| elem = ArrX_Buf_search_i( &Errors_Fin_buf, &Errors_Fin_key, 1227| fin, Errors_FinElem ); 1228| if ( elem == NULL ) { 1229| elem = ArrX_Buf_alloc( &Errors_Fin_buf, Errors_FinElem ); 1230| strncpy( elem->name, name, ERRORS_FINISHCHK_MNAME ); 1231| elem->name[ERRORS_FINISHCHK_MNAME-1] = '\0'; 1232| elem->funcAdr = fin; 1233| } 1234| Errors_printf( "FinishChk count1 = %d, count2 = %d", 1235| elem->count, ArrX_Able_getN( &Errors_FinishChk_ptrs, ArrX_AbleElemP ) ); 1236| if ( elem->count != ArrX_Able_getN( &Errors_FinishChk_ptrs, ArrX_AbleElemP ) ) { 1237| Errors_break( 0x4141 ); 1238| error(); 1239| } 1240| } 1241| #else 1242| name, _finish; /* avoid warning */ 1243| #endif 1244|} 1245|#endif 1246| 1247| 1248|/*********************************************************************** 1249| 5-11. <<< [Errors_setStart_imp] 初期設定値を変更する >>> 1250|【引数】 1251| ・int r6; 初期設定値 1252| ・int* r7; 初期設定変数 1253|【補足】 1254|・デバッガで、r6 を修正することで、*r7 の値を設定します。 1255|・再コンパイルしなくても初期値を変更することができます。 1256|************************************************************************/ 1257|void Errors_setStart_imp( int r6, int* r7 ) 1258|{ 1259| *r7 = r6; 1260|} 1261| 1262| 1263|/*--------------------------------------------------------------------*/ 1264|/* 6. <<<<◆ デバッグツール >>>> */ 1265|/*--------------------------------------------------------------------*/ 1266| 1267|char* Errors_ps = "%s"; 1268|char* Errors_ns = ""; 1269|char* Errors_eu = "Errors_Unofficial"; 1270|char* Errors_ea = "Errors_ASSERT"; 1271|char* Errors_null = "(e-null)"; 1272| 1273|char* Errors_printToMemory( const char* msg ); 1274|void Errors_printToConsole( const char* msg ); 1275|void Errors_printToWindows( const char* msg ); 1276|void Errors_printToFile( const char* msg ); 1277|void Errors_printToPB( const char* msg ); 1278| 1279|#if !defined(NDEBUG) || defined(ERRORS_ERROR_REPORT) 1280| char* Errors_appName = NULL; 1281| char* Errors_appVersion = NULL; 1282| struct HWND__* Errors_parentWnd = NULL; 1283| void* Errors_parentCWnd = NULL; /* CWnd* 型にキャストして使う */ 1284|#endif 1285| 1286|#ifdef ERRORS_PRINTF_TO_FILE 1287| #ifndef USES_FILEX 1288| #error Need FileX if define ERRORS_PRINTF_TO_FILE 1289| #endif 1290|#endif 1291| 1292|/*************************************************************************** 1293| 6-1. <<< [Errors_backmark_imp] BACKMARK の関数部 >>> 1294|****************************************************************************/ 1295|#if defined(ERRORS_USE_BACKMARK) && defined(USES_FILEX) && defined(ERRORS_PRINTF_TO_FILE) 1296|void Errors_backmark_imp( const char* file, int line ) 1297|{ 1298| char s[_MAX_PATH + 20]; 1299| 1300| sprintf( s, "MARK %s(%d)", file, line ); 1301| Errors_printToFile( s ); 1302|} 1303|#endif 1304| 1305| 1306|/*************************************************************************** 1307| 6-2. <<< [Errors_counter_imp] カウンタ、この関数の呼び出し回数を数えます。 >>> 1308|【引数】 1309| ・int stop_count; 返り値を 1 にする呼び出し回数 1310| ・int 返り値; カウンタが stop_count になると 1(not=0) 1311|【補足】 1312|・最新版の COUNT マクロを使用してください。 1313|・回数を数えたい実行経路に置きます。 1314|・その経路を通る回数を調べるときは、引数 stop_count を 0 にして、 1315| 実行後、グローバル変数 Errors_count を参照します。 1316|・指定された回数呼び出されると返り値が0以外になるので、 1317| それを判断して、ブレークポイント(brk)を付けたりします。 1318|【例】 1319|・stop_count==3 なら、返り値は 1,2,0,1,2,0,1,2,0.... 1320|・if ( Errors_counter(0) ) 1321| { int i; i++; } ... ここにブレークポイントを張る 1322|****************************************************************************/ 1323|int Errors_count = 0; 1324|int Errors_count0 = 0; 1325| 1326|char* Errors_count_prev_n_file; 1327|int Errors_count_prev_n_line; 1328|int Errors_count_prev_n; 1329| 1330|int Errors_count2 = 0; 1331|int Errors_count2_0 = 0; 1332| 1333|char* Errors_count2_prev_n_file; 1334|int Errors_count2_prev_n_line; 1335|int Errors_count2_prev_n; 1336| 1337|int Errors_count_b = 1; 1338|int Errors_count_b2 = 1; 1339| 1340|#if 0 1341|int Errors_counter_imp( int stop_count ) 1342|{ 1343| Errors_count ++; 1344| return ( stop_count > 0 && 1345| Errors_count % stop_count == 0 ); 1346|} 1347|#endif 1348| 1349|/************************************************************************** 1350| 6-3. <<< [Errors_WD_imp] WD の実装 >>> 1351|***************************************************************************/ 1352|#ifndef ERRORS_CUT_DEBUG_TOOL 1353|void Errors_WD_imp( char* name, void* p, int ver, 1354| char* file, int line ) 1355|{ 1356| Errors_printf( "%s (%p) = %d(0x%X) \'%c\' : %s(%d)", 1357| name, p, ver, ver, Errors_getDispCh( ver ), file, line ); 1358|} 1359|#endif 1360| 1361|/************************************************************************** 1362| 6-4. <<< [Errors_WSP_imp] WSP の実装 >>> 1363|***************************************************************************/ 1364|#ifndef ERRORS_CUT_DEBUG_TOOL 1365|void Errors_WSP_imp( char* name, const char** p, const char* ver, 1366| char* file, int line ) 1367|{ 1368| enum { s_size = 20 }; 1369| char s[s_size]; 1370| char* sp; 1371| char* sp_over = s + s_size - 1; 1372| const char* vp; 1373| 1374| for ( sp = s, vp = ver; sp < sp_over; sp++, vp++ ) { 1375| *sp = Errors_getDispCh( *vp ); 1376| } 1377| *sp = '\0'; 1378| 1379| Errors_printf( "%s (%p) = %p \"%s\" : %s(%d)", name, p, ver, s, file, line ); 1380|} 1381|#endif 1382| 1383|/************************************************************************** 1384| 6-5. <<< [Errors_WX_imp] WX の実装 >>> 1385|***************************************************************************/ 1386|#ifndef ERRORS_CUT_DEBUG_TOOL 1387|void Errors_WX_imp( char* adr_name, void* adr, int size, char* file, int line ) 1388|{ 1389| unsigned char* p = (unsigned char*)adr; 1390| unsigned char* p_over = (unsigned char*)adr + size; 1391| unsigned char* cp; 1392| unsigned char* cp_over; 1393| char* sp; 1394| char sline[256]; 1395| 1396| if ( size < 0x10 ) { 1397| sp = sline; 1398| sprintf( sp, "%s(%08X) %08X : ", adr_name, adr, p ); sp = strchr( sp, '\0' ); 1399| for ( cp = p; cp < p_over; cp++ ) { 1400| if ( cp >= p && cp < p_over ) { 1401| sprintf( sp, "%02X%s", *cp, 1402| ((int)(cp - p) & 0x3) == 3 && cp < p_over - 1 ? " - " : " " ); 1403| } 1404| else sprintf( sp, " " ); 1405| sp = strchr( sp, '\0' ); 1406| } 1407| for ( cp = p; cp < p_over; cp++ ) { 1408| if ( cp >= p && cp < p_over ) sprintf( sp, "%c", Errors_getDispCh( *cp ) ); 1409| else sprintf( sp, " " ); 1410| sp++; 1411| } 1412| sprintf( sp, ": %s(%d)", file, line ); 1413| Errors_printf( "%s", sline ); 1414| } 1415| else { 1416| Errors_printf( "%s(%08X) : size = %d(0x%X) : %s(%d)", adr_name, adr, 1417| size, size, file, line ); 1418| for ( ; p < p_over; p += 0x10 ) { 1419| if ( p >= (unsigned char*)adr + 0x10 * ERRORS_WX_NLINE && 1420| p < p_over - 0x10 * ERRORS_WX_NLINE ) { 1421| if ( p == (unsigned char*)adr + 0x10 * ERRORS_WX_NLINE ) 1422| Errors_printf( " : " ); 1423| continue; 1424| } 1425| sp = sline; 1426| sprintf( sp, "%s %08X : ", adr_name, p ); sp = strchr( sp, '\0' ); 1427| cp_over = p + 0x10; 1428| for ( cp = p; cp < cp_over; cp++ ) { 1429| if ( cp >= p && cp < p_over ) { 1430| sprintf( sp, "%02X%s", *cp, 1431| ((int)cp & 0x3) == 3 && cp < cp_over - 1 ? " - " : " " ); 1432| } 1433| else sprintf( sp, " " ); 1434| sp = strchr( sp, '\0' ); 1435| } 1436| for ( cp = p; cp < cp_over; cp++ ) { 1437| if ( cp >= p && cp < p_over ) sprintf( sp, "%c", Errors_getDispCh( *cp ) ); 1438| else sprintf( sp, " " ); 1439| sp++; 1440| } 1441| Errors_printf( "%s", sline ); 1442| } 1443| } 1444|} 1445|#endif 1446| 1447|/************************************************************************** 1448| 6-6. <<< [Errors_WX2_imp] WX2 の実装 >>> 1449|***************************************************************************/ 1450|#ifndef ERRORS_CUT_DEBUG_TOOL 1451|void Errors_WX2_imp( char* adr_name, void* adr, int size, char* file, int line ) 1452|{ 1453| unsigned char* p = (unsigned char*)( (int)adr & 0xFFFFFFF0 ); 1454| unsigned char* p_over = (unsigned char*)( ((int)adr + size + 0xF) & 0xFFFFFFF0 ); 1455| unsigned char* adr_over = (unsigned char*)adr + size; 1456| unsigned char* cp; 1457| unsigned char* cp_over; 1458| char* sp; 1459| char sline[80]; 1460| 1461| if ( p_over - p == 0x10 ) { 1462| sp = sline; 1463| sprintf( sp, "%s(%08X) %08X : ", adr_name, adr, p ); sp = strchr( sp, '\0' ); 1464| for ( cp = p; cp < p_over; cp++ ) { 1465| if ( cp >= (unsigned char*)adr && cp < adr_over ) 1466| sprintf( sp, "%02X%s", *cp, ((int)cp & 0x3) == 3 ? " - " : " " ); 1467| else sprintf( sp, " " ); 1468| sp = strchr( sp, '\0' ); 1469| } 1470| sprintf( sp, ": %s(%d)", file, line ); 1471| Errors_printf( "%s", sline ); 1472| } 1473| else { 1474| Errors_printf( "%s(%08X) : size = %d(0x%X) : %s(%d)", adr_name, adr, 1475| size, size, file, line ); 1476| for ( ; p < p_over; p += 0x10 ) { 1477| sp = sline; 1478| sprintf( sp, "%s %08X : ", adr_name, p ); sp = strchr( sp, '\0' ); 1479| cp_over = p + 0x10; 1480| for ( cp = p; cp < cp_over; cp++ ) { 1481| if ( cp >= (unsigned char*)adr && cp < adr_over ) 1482| sprintf( sp, "%02X%s", *cp, ((int)cp & 0x3) == 3 ? " - " : " " ); 1483| else sprintf( sp, " " ); 1484| sp = strchr( sp, '\0' ); 1485| } 1486| Errors_printf( "%s", sline ); 1487| } 1488| } 1489|} 1490|#endif 1491| 1492|/************************************************************************** 1493| 6-7. <<< [Errors_setWATCH_imp, Errors_WATCH_imp] WATCH, setWATCH の実装 >>> 1494|***************************************************************************/ 1495|#ifndef ERRORS_CUT_DEBUG_TOOL 1496|void* Errors_WATCH_adr = NULL; 1497|int Errors_WATCH_size = 0; 1498|int Errors_WATCH_type = Errors_WATCH_Bin; 1499|char Errors_WATCH_prevData[256]; 1500|bool Errors_bWatchLookAtCount; 1501| 1502|void Errors_setWATCH_imp( void* adr, char* name, int type, int size, 1503| bool lookAtCount, char* file, int line ) 1504|{ 1505| enum { n = 4 }; 1506| enum { s_size = n*(sizeof(int)*2+1) }; 1507| char s[s_size]; 1508| char* adr_over; 1509| char* prev = Errors_WATCH_prevData; 1510| char* sp; 1511| const int* pp; 1512| const int* pp_over; 1513| 1514| ASSERT( size <= (int)sizeof( Errors_WATCH_prevData ) ); 1515| ASSERT( type == Errors_WATCH_Bin || type == Errors_WATCH_CharP ); 1516| Errors_WATCH_adr = adr; 1517| Errors_WATCH_size = size; 1518| Errors_WATCH_type = type; 1519| Errors_bWatchLookAtCount = lookAtCount; 1520| 1521| if ( adr == NULL ) { 1522| Errors_printf( "first WATCH!★ : %s (adr = NULL, size = 0x%X) : %s(%d)", name, size, file, line ); 1523| } 1524| else { 1525| if ( type == Errors_WATCH_Bin ) { 1526| memcpy( prev, adr, size ); 1527| adr_over = (char*)adr + size; 1528| for ( ; (char*)adr < adr_over; adr = (char*)adr + n*8 ) { 1529| pp_over = (int*)adr + n; 1530| for ( pp = (const int*)adr, sp = s; pp < pp_over; pp++ ) { 1531| sprintf( sp, "%08X", *pp ); 1532| sp += 8; *sp = ' '; sp ++; 1533| } 1534| *(sp - 1) = '\0'; 1535| Errors_printf( "first WATCH!★ : %s (adr = %p, size = 0x%X) : %s : %s(%d)", 1536| name, adr, size, s, file, line ); 1537| } 1538| } 1539| else { ASSERT( type == Errors_WATCH_CharP ); 1540| strncpy( prev, (char*)adr, sizeof( Errors_WATCH_prevData ) ); 1541| Errors_printf( "first WATCH!★ : %s (adr = %p) : %s : %s(%d)", 1542| name, adr, adr, file, line ); 1543| } 1544| } 1545|} 1546| 1547|void Errors_WATCH_imp( char* file, int line ) 1548|{ 1549| enum { n = 4 }; 1550| enum { s_size = n*(sizeof(int)*2+1) }; 1551| char s[s_size]; 1552| char* adr = (char*)Errors_WATCH_adr; 1553| char* adr_over; 1554| int size = Errors_WATCH_size; 1555| char* prev = Errors_WATCH_prevData; 1556| char* sp; 1557| const int* pp; 1558| const int* pp_over; 1559| int f; 1560| bool bChg = false; 1561| 1562| if ( adr == NULL ) { 1563| Errors_printf( "WATCH : no change : %s(%d)", file, line ); 1564| return; 1565| } 1566| 1567| if ( Errors_WATCH_type == Errors_WATCH_Bin ) { 1568| adr_over = adr + size; 1569| for ( ; adr < adr_over; adr += n*8 ) { 1570| if ( adr_over - adr > n*8 ) f = memcmp( prev, adr, n*8 ); 1571| else f = memcmp( prev, adr, adr_over - adr ); 1572| 1573| if ( f != 0 ) { 1574| pp_over = (int*)adr + n; 1575| for ( pp = (const int*)adr, sp = s; pp < pp_over; pp++ ) { 1576| sprintf( sp, "%08X", *pp ); 1577| sp += 8; *sp = ' '; sp ++; 1578| } 1579| *(sp - 1) = '\0'; 1580| Errors_printf( "WATCH!★ : adr = %p : %s : %s(%d)", adr, s, file, line ); 1581| bChg = true; 1582| } 1583| } 1584| memcpy( prev, Errors_WATCH_adr, size ); 1585| } 1586| else { ASSERT( Errors_WATCH_type == Errors_WATCH_CharP ); 1587| if ( strncmp( prev, adr, sizeof(Errors_WATCH_prevData) ) != 0 ) { 1588| Errors_printf( "WATCH!★ : adr = %p : %s : %s(%d)", 1589| adr, adr, file, line ); 1590| bChg = true; 1591| } 1592| strncpy( prev, adr, sizeof( Errors_WATCH_prevData ) ); 1593| } 1594| 1595| if ( ! bChg ) 1596| Errors_printf( "WATCH : no change : %s(%d)", file, line ); 1597|} 1598|#endif 1599| 1600| 1601|/*************************************************************************** 1602| 6-8. <<< [Errors_log] デバッグ表示の記録(ログ)>>> 1603| 6-9. <<< [Errors_log2] エラーメッセージの記録(ログ)>>> 1604|【補足】 1605|・エラーが発生したり、ブレークしたりすると、Errors_printf_flush 関数に 1606| よって、このログの内容がファイルに出力されます。(ファイルシステムを 1607| 装備している場合) 1608|・ログの容量が足らない場合、errors_log の配列要素数を増やしてください。 1609| それでも、増えないと感じた場合、ビューアに取り込むサイズを確認してください。 1610|・ログの容量を越えて記録した場合、もう一度ログの最初から記録を開始します。 1611| 最初に戻る前にブレークさせることもできます。(→bf2 関数) 1612|****************************************************************************/ 1613|char Errors_log[Errors_log_size]; 1614|char* Errors_log_p = Errors_log; 1615|int Errors_LogTop_iPage = 1; 1616| 1617|char Errors_log2[0x777]; 1618|char* Errors_log2_p = Errors_log2; 1619| 1620|char Errors_log_testCase[1024]; 1621| 1622|char* Errors_poolStart = NULL; /* ため始める位置、Errors_log へのポインタ */ 1623| /* NULL=ためていない */ 1624| 1625| 1626| 1627|/************************************************************************** 1628| 6-10. <<< [Errors_printf_imp] デバッグ用 printf >>> 1629|【引数】 1630| ・printf と同じ 1631| ・char* 返り値; 今回のメッセージの文字列先頭アドレス(ログの中) 1632|【補足】 1633|・Errors_printf の実装部分です 1634|・デバッグするときに使います。リリース版でも使えます。 1635|・デバッグが終了したら ERRORS_CUT_DEBUG_TOOL を設定してコンパイルすれば、 1636| 容易にすべてのデバッグツールをカットすることができます。 1637|・メモリに表示しない場合、返り値は NULL です。 1638|・どのような表示媒体を使用するかは、ERRORS_PRINTF_TO_WINDOW などの 1639| 設定によります。 1640|***************************************************************************/ 1641|char* Errors_printf_imp( const char* fmt, ... ) 1642|{ 1643| char* ret; 1644| va_list va; 1645| 1646| va_start( va, fmt ); 1647| ret = Errors_printf_imp2( fmt, va ); 1648| va_end( va ); 1649| 1650| return ret; 1651|} 1652| 1653| 1654| 1655|/************************************************************************** 1656| 6-11. <<< [Errors_printf_imp2] Errors_printf_imp のサブルーチン >>> 1657|***************************************************************************/ 1658|char* Errors_printf_imp2( const char* fmt, va_list va ) 1659|{ 1660| #ifdef ERRORS_PRINTF_TO_MEMORY 1661| char* ret; 1662| #else 1663| char* ret = NULL; 1664| #endif 1665| char msg[8192]; 1666| 1667| if ( ! Errors_printfFlag ) return NULL; 1668| 1669| vsprintf( msg, fmt, va ); 1670| if ( strlen( msg ) > sizeof(msg) ) { 1671| strcpy( msg + sizeof(msg) - 5, "..." ); 1672| bf( Errors_ErrValue, 0, (int)__FILE__, __LINE__ ); 1673| Errors_printLowLevel( "Errors_printf msg block was over." ); 1674| Errors_exit( __FILE__,__LINE__ ); 1675| } 1676| 1677| #ifdef ERRORS_PRINTF_TO_WINDOW 1678| if ( Errors_poolStart == NULL ) 1679| Errors_printToWindows( msg ); 1680| #endif 1681| 1682| #ifdef ERRORS_PRINTF_TO_STDOUT 1683| Errors_printToConsole( msg ); 1684| #endif 1685| 1686| #ifdef ERRORS_PRINTF_TO_STDERR 1687| fprintf( stderr, "%s\r\n", msg ); 1688| #endif 1689| 1690| #ifdef ERRORS_PRINTF_TO_FILE 1691| Errors_printToFile( msg ); 1692| #endif 1693| 1694| #ifdef ERRORS_PRINTF_TO_MEMORY 1695| ret = Errors_printToMemory( msg ); 1696| #else 1697| #ifndef NDEBUG 1698| if ( Errors_poolStart != NULL ) { 1699| static int f = 0; 1700| 1701| f++; 1702| if ( f == 1 ) 1703| Errors_printLowLevel( "エラーメッセージを格納する ERRORS_PRINTF_TO_MEMORY の設定が必要です。" ); 1704| } 1705| #endif 1706| #endif 1707| 1708| #ifdef ERRORS_PRINTF_TO_PB 1709| Errors_printToPB( msg ); 1710| #endif 1711| 1712| return ret; 1713|} 1714| 1715| 1716| 1717|/************************************************************************** 1718| 6-12. <<< [Errors_printf_back_imp] Errors_printf_back の関数部 >>> 1719|***************************************************************************/ 1720|#if defined(ERRORS_USE_BACKMARK) && defined(USES_FILEX) && defined(ERRORS_PRINTF_TO_FILE) 1721|void Errors_printf_back_imp( const char* fmt, ... ) 1722|{ 1723| va_list va; 1724| char msg[8192]; 1725| 1726| va_start( va, fmt ); 1727| vsprintf( msg, fmt, va ); 1728| va_end( va ); 1729| 1730| Errors_printToFile( msg ); 1731|} 1732|#endif 1733| 1734|/*************************************************************************** 1735| 6-13. <<< [Errors_printfFlag] 表示フラグ >>> 1736|【補足】 1737|・参考:Errors_setPrintfFlag, Errors_breakFlag 1738|****************************************************************************/ 1739|bool Errors_printfFlag = true; /* 表示フラグ */ 1740|bool Errors_bPrintFileFirst = true; 1741|char* Errors_fileName = "errlog.txt"; 1742| 1743|/************************************************************************** 1744| 6-14. <<< [Errors_printf_release] リリース用エラー printf >>> 1745|【補足】 1746|・リリースするプログラムの標準的なエラー表示に使います。 1747|***************************************************************************/ 1748|char* Errors_printf_release( const char* fmt, ... ) 1749|{ 1750| char msg[1024]; 1751| va_list va; 1752| #ifdef ERRORS_ERR_PRINTF_TO_MEMORY 1753| char* ret; 1754| #else 1755| char* ret = NULL; 1756| #endif 1757| 1758| va_start( va, fmt ); 1759| vsprintf( msg, fmt, va ); 1760| if ( strlen( msg ) > sizeof(msg) ) { 1761| strcpy( msg + sizeof(msg) - 4, "..." ); 1762| bf( Errors_ErrValue, 0, (int)__FILE__, __LINE__ ); 1763| } 1764| va_end( va ); 1765| 1766| #ifdef ERRORS_ERR_PRINTF_TO_WINDOW 1767| if ( Errors_poolStart == NULL ) 1768| Errors_printToWindows( msg ); 1769| #endif 1770| 1771| #ifdef ERRORS_ERR_PRINTF_TO_STDOUT 1772| Errors_printToConsole( msg ); 1773| #endif 1774| #ifdef ERRORS_ERR_PRINTF_TO_STDERR 1775| fprintf( stderr, "%s\r\n", msg ); 1776| #endif 1777| 1778| #if defined(ERRORS_ERR_PRINTF_TO_FILE) && ! defined(ERRORS_CUT_DEBUG_TOOL) 1779| Errors_printToFile( msg ); 1780| #endif 1781| 1782| #ifdef ERRORS_ERR_PRINTF_TO_MEMORY 1783| ret = Errors_printToMemory( msg ); 1784| #else 1785| #ifndef NDEBUG 1786| if ( Errors_poolStart != NULL ) { 1787| static int f = 0; 1788| 1789| f++; 1790| if ( f == 1 ) 1791| Errors_printLowLevel( "エラーメッセージを格納する ERRORS_ERR_PRINTF_TO_MEMORY の設定が必要です。" ); 1792| } 1793| #endif 1794| #endif 1795| 1796| #ifdef ERRORS_ERR_PRINTF_TO_PB 1797| Errors_printToPB( msg ); 1798| #endif 1799| 1800| return ret; 1801|} 1802| 1803| 1804| 1805|/************************************************************************** 1806| 6-15. <<< [Errors_errPrintf] テストエラー用 printf >>> 1807|【補足】 1808|・通常の Errors_printf の出力が多すぎるときに、通常とは別のバッファに 1809| テスト・プログラムのエラー表示を行うときに使います。 1810|・前回の Errors_testCasePrintf で登録されたテストケース情報を 1811| 出力してから、本関数の引数を出力します。 1812|・変数 Errors_log2(errlog2.txt ファイル) に出力されます。 1813| ただし、ファイルに出力する場合は、ERRORS_PRINTF_FLUSH を使います。 1814|・Errors_log にも出力します。 1815|***************************************************************************/ 1816|char* Errors_errPrintf( const char* fmt, ... ) 1817|{ 1818| char msg[1024]; 1819| va_list va; 1820| char* ret; 1821| 1822| va_start( va, fmt ); 1823| vsprintf( msg, fmt, va ); 1824| if ( strlen( msg ) > sizeof(msg) ) { 1825| strcpy( msg + sizeof(msg) - 4, "..." ); 1826| bf( Errors_ErrValue, 0, (int)__FILE__, __LINE__ ); 1827| } 1828| va_end( va ); 1829| 1830| Errors_printf_release( "%s", msg ); 1831| 1832| ret = Errors_log2_p; 1833| if ( Errors_log2_p < Errors_log2 + sizeof(Errors_log2) - sizeof(msg) ) { 1834| 1835| /* テストケースを出力する */ 1836| if ( Errors_log_testCase[0] != '\0' ) { 1837| strcpy( Errors_log2_p, Errors_log_testCase ); 1838| Errors_log_testCase[0] = '\0'; 1839| Errors_log2_p = strchr( Errors_log2_p, '\0' ); 1840| *Errors_log2_p = '\r'; Errors_log2_p ++; 1841| *Errors_log2_p = '\n'; Errors_log2_p ++; 1842| } 1843| /* エラーメッセージを出力する */ 1844| strcpy( Errors_log2_p, msg ); 1845| Errors_log2_p = strchr( Errors_log2_p, '\0' ); 1846| *Errors_log2_p = '\r'; Errors_log2_p ++; 1847| *Errors_log2_p = '\n'; Errors_log2_p ++; 1848| } 1849| 1850| #ifdef ERRORS_PRINTF_TO_FILE 1851| #ifndef USES_FILEX 1852| #error need FileX 1853| #endif 1854| #ifdef FOR_WINCE 1855| #error not support 1856| #endif 1857| { 1858| FILE* f; 1859| static int bFirst = true; 1860| 1861| if ( Errors_bPrintFileFirst ) { 1862| remove( "errlog4.txt" ); Errors_bPrintFileFirst = false; 1863| } 1864| f = FileX_open( "errlog4.txt", "ab+" ); 1865| fputs( msg, f ); fputc( '\r', f ); fputc( '\n', f ); 1866| fclose( f ); 1867| } 1868| #endif 1869| 1870| return ret; 1871|} 1872| 1873| 1874| 1875|/************************************************************************** 1876| 6-16. <<< [Errors_testCasePrintf] テストケース出力用 printf >>> 1877|【補足】 1878|・テストケースを表示するために使用します。 1879|・すぐに変数 Errors_log に出力しますが、次の Errors_errPrintf で 1880| 最新の Errors_testcasePrintf で出力した内容を、変数 Errors_log2 にも 1881| 出力します。 1882|***************************************************************************/ 1883|char* Errors_testCasePrintf( const char* fmt, ... ) 1884|{ 1885| char msg[1024]; 1886| va_list va; 1887| 1888| va_start( va, fmt ); 1889| vsprintf( msg, fmt, va ); 1890| if ( strlen( msg ) > sizeof(msg) ) { 1891| strcpy( msg + sizeof(msg) - 4, "..." ); 1892| bf( Errors_ErrValue, 0, (int)__FILE__, __LINE__ ); 1893| } 1894| va_end( va ); 1895| 1896| Errors_printf_release( "%s", msg ); 1897| strcpy( Errors_log_testCase, msg ); 1898| 1899| return Errors_log_testCase; 1900|} 1901| 1902| 1903| 1904|/************************************************************************** 1905| 6-17. <<< [Errors_printSize] サイズ出力用 printf >>> 1906|【引数】 1907| ・char* guide; ガイド(何のサイズかの説明) 1908| ・int size; サイズ(バイト) 1909|【補足】 1910|・KB, MB の出力もします。 1911|***************************************************************************/ 1912|#ifndef ERRORS_CUT_DEBUG_TOOL 1913|void Errors_printSize( const char* guide, int size ) 1914|{ 1915| #ifdef FOR_32BIT 1916| Errors_printf_release( " %s = %d, 0x%X, %dKB, %fMB", 1917| guide, size, size, size / 1024, (float)size / (1024*1024) ); 1918| #endif 1919|} 1920|#endif 1921| 1922| 1923|/************************************************************************** 1924| 6-18. <<< [ERRORS_PRINTF_FLUSH] エラーメッセージのログを出力する >>> 1925|【補足】 1926|・エラーでなくても、Errors_printf のログを出力したい場合は、 1927| メイン関数の最後でこの関数を呼び出します。 1928|・リリース時は、無効になります。 1929|・この関数を呼び出すたびに前のページ番号が出力されてしまいます。(バグ) 1930| 1931| 6-19. <<< [errlog] エラーログファイル >>> 1932|・errlog.txt は、ERRORS_PRINTF_TO_FILE による出力です。 1933|・errlog1.txt は、Errors_log 領域の出力です。 1934|・errlog2.txt は、Errors_log2 領域の出力です。 1935|***************************************************************************/ 1936|#if 0 1937|#ifndef ERRORS_CUT_DEBUG_TOOL 1938|void ERRORS_PRINTF_FLUSH() 1939|{ 1940| #ifndef FOR_NOFILE 1941| { 1942| FILE* file = fopen( "errlog1.txt", "wb" ); 1943| if ( Errors_LogTop_iPage == 1 ) 1944| fwrite( Errors_log, 1, Errors_log_p - Errors_log, file ); 1945| else 1946| fwrite( Errors_log, 1, sizeof(Errors_log), file ); 1947| fclose( file ); 1948| 1949| file = fopen( "errlog2.txt", "wb" ); 1950| fwrite( Errors_log2, 1, Errors_log2_p - Errors_log2, file ); 1951| fclose( file ); 1952| } 1953| #endif 1954|} 1955|#endif 1956|#endif 1957| 1958| 1959| 1960|/************************************************************************** 1961| 6-20. <<< [Errors_clearLog] エラーメッセージの記録をクリアする >>> 1962|***************************************************************************/ 1963|void Errors_clearLog() 1964|{ 1965| int i; 1966| 1967| for ( i = 0; i < Errors_log_size; i++ ) 1968| Errors_log[i] = '\0'; 1969| Errors_log_p = Errors_log; 1970| Errors_LogTop_iPage = 1; 1971| 1972| for ( i = 0; i < sizeof(Errors_log2); i++ ) 1973| Errors_log2[i] = '\0'; 1974| Errors_log2_p = Errors_log2; 1975| 1976| for ( i = 0; i < sizeof(Errors_log_testCase); i++ ) 1977| Errors_log_testCase[i] = '\0'; 1978|} 1979| 1980| 1981| 1982|/************************************************************************** 1983| 6-21. <<< [Errors_getDispCh] 表示可能な文字を返す >>> 1984|***************************************************************************/ 1985|int Errors_getDispCh( int c ) 1986|{ 1987| if ( c == '\0' ) return '0'; 1988| else if ( c == '\r' ) return ' '; 1989| else if ( c == '\n' ) return ' '; 1990| else if ( c > 0x100 || c < 0x20 ) return '.'; 1991| else return c; 1992|} 1993| 1994|/************************************************************************** 1995| 6-22. <<< [Errors_printToMemory] メモリ出力 >>> 1996|【内部補足】 1997|・Errors_printLowLevel から呼ばれます。 1998|***************************************************************************/ 1999|char* Errors_printToMemory( const char* msg ) 2000|{ 2001| char* ret; 2002| 2003| if ( Errors_log_p >= Errors_log + sizeof(Errors_log) - strlen(msg) - 23 ) { 2004| memset( Errors_log_p, 0, Errors_log + sizeof(Errors_log) - Errors_log_p ); 2005| #ifdef FOR_32BIT 2006| bf2( 0xBBBBFFFF, Errors_LogTop_iPage, (int)__FILE__,__LINE__); 2007| #else 2008| bf2( 0xBBFF, Errors_LogTop_iPage, (int)__FILE__,__LINE__); 2009| #endif 2010| Errors_LogTop_iPage ++; 2011| Errors_log_p = Errors_log; 2012| sprintf( Errors_log_p, "--- Page %d\r\n", Errors_LogTop_iPage ); 2013| Errors_log_p = strchr( Errors_log_p, '\0' ); 2014| } 2015| ret = Errors_log_p; 2016| strcpy( Errors_log_p, msg ); 2017| Errors_log_p = strchr( Errors_log_p, '\0' ); 2018| *Errors_log_p = '\r'; Errors_log_p ++; 2019| *Errors_log_p = '\n'; Errors_log_p ++; 2020| if ( Errors_LogTop_iPage == 1 ) 2021| *Errors_log_p = '\0'; 2022| else { 2023| sprintf( Errors_log_p, "\r\n--- Page %d\r\n", Errors_LogTop_iPage - 1 ); 2024| *strchr( Errors_log_p, '\0' ) = ' '; 2025| } 2026| 2027| return ret; 2028|} 2029| 2030|/************************************************************************** 2031| 6-23. <<< [Errors_printToConsole] 標準出力 >>> 2032|【内部補足】 2033|・Errors_printLowLevel から呼ばれます。 2034|***************************************************************************/ 2035|#if ( defined(USES_STDLIBS) || defined(FOR_DOS32) ) && ! defined(UNDER_CE) 2036|void Errors_printToConsole( const char* msg ) 2037|{ 2038| puts( msg ); 2039|} 2040|#endif 2041| 2042|/************************************************************************** 2043| 6-24. <<< [Errors_printToWindows] ダイアログ出力 >>> 2044|【内部補足】 2045|・Errors_printLowLevel から呼ばれます。 2046|***************************************************************************/ 2047|#if defined(FOR_WIN32) 2048|void Errors_printToWindows( const char* msg ) 2049|{ 2050| if ( MessageBox( (HWND)Errors_parentWnd, msg, 2051| "エラーメッセージ", MB_OKCANCEL | MB_ICONERROR ) 2052| == IDCANCEL ) { 2053| Errors_bStrongExit = true; 2054| Errors_exit(__FILE__,__LINE__); 2055| } 2056|} 2057|#endif 2058| 2059|/************************************************************************** 2060| 6-25. <<< [Errors_printToFile] ファイル出力 >>> 2061|【内部補足】 2062|・Errors_printLowLevel から呼ばれます。 2063|・実行ファイルのあるパスに出力します。 2064|***************************************************************************/ 2065|#ifdef USES_FILEX 2066|#ifdef USES_STRX 2067|#ifndef FOR_WINCE 2068|void Errors_printToFile( const char* msg ) 2069|{ 2070| FILE* f; 2071| char path[_MAX_PATH]; 2072| 2073| if ( StrX_argv0 == NULL ) { 2074| static bool b = false; 2075| 2076| if ( ! b ) { 2077| Errors_printLowLevel( "StrX_argv0 が初期化されていないため、" 2078| "Errors_printToFile が実行できません。" ); 2079| b = true; 2080| } 2081| return; 2082| } 2083| 2084| StrX_getExeFullPath( path, Errors_fileName, sizeof(path) ); 2085| if ( Errors_bPrintFileFirst ) { 2086| remove( path ); 2087| Errors_bPrintFileFirst = false; 2088| 2089| #ifndef ERRORS_CUT_DEBUG_TOOL 2090| { 2091| char msg2[_MAX_PATH + 256]; 2092| 2093| sprintf( msg2, "Error Message put to %s", path ); 2094| #ifdef ERRORS_ERR_PRINTF_TO_WINDOW 2095| if ( Errors_poolStart == NULL ) 2096| Errors_printToWindows( msg2 ); 2097| #endif 2098| #ifdef ERRORS_ERR_PRINTF_TO_STDOUT 2099| Errors_printToConsole( msg2 ); 2100| #endif 2101| #ifdef ERRORS_ERR_PRINTF_TO_STDERR 2102| fprintf( stderr, "%s\r\n", msg2 ); 2103| #endif 2104| #ifdef ERRORS_ERR_PRINTF_TO_MEMORY 2105| Errors_printToMemory( msg2 ); 2106| #endif 2107| } 2108| #endif 2109| } 2110| f = fopen( path, "ab+" ); 2111| if ( f == NULL ) { 2112| Errors_printLowLevel( "エラーファイルが開けません。" ); 2113| Errors_printLowLevel( path ); 2114| return; 2115| } 2116| fputs( msg, f ); fputc( '\r', f ); fputc( '\n', f ); 2117| fclose( f ); 2118|} 2119|#endif 2120|#endif 2121|#endif 2122| 2123|/************************************************************************** 2124| 6-26. <<< [Errors_printToPB] Platform Builder デバッグ・メッセージ出力 >>> 2125|【補足】 2126|・RETAILMSG を使用しています。 2127|・msg は、Shift Jis コードの文字列です。(Unicode ではありません) 2128|***************************************************************************/ 2129|#ifdef FOR_WINCE 2130|void Errors_printToPB( const char* msg ) 2131|{ 2132| wchar_t s[4096]; 2133| 2134|// setlocale( LC_ALL, "Japanese" ); 2135|// mbstowcs( s, msg, sizeof(s) ); 2136| 2137| MultiByteToWideChar( CP_ACP, 0, msg, -1, s, sizeof(s) ); 2138| RETAILMSG(1, (TEXT("%s\r\n"), s )); 2139|} 2140|#endif 2141| 2142|/************************************************************************** 2143| 6-27. <<< [Errors_printLowLevel] 低レベル出力 >>> 2144|【補足】 2145|・エラー出力システムが初期化できないときに使用します。 2146|・確実にプログラマに伝える方法を環境に応じて変えます。 2147|***************************************************************************/ 2148|void Errors_printLowLevel( const char* msg ) 2149|{ 2150| #if defined(FOR_DOS32) 2151| Errors_printToConsole( msg ); 2152| #elif defined(FOR_WIN32) 2153| Errors_printToWindows( msg ); 2154| #else 2155| Errors_printToMemory( msg ); 2156| #endif 2157|} 2158| 2159| 2160|/*************************************************************************** 2161| 6-28. <<< [bf, _bf, bf2] ブレークポイントが実際に止まる場所 >>> 2162|【引数】 2163| ・int 返り値; Errors_nextBreakCount に設定する値 2164| (その他は Errors_break_imp 関数を参照) 2165|【補足】 2166|・アセンブラ・デバッガでは、_bf にブレークポイントを付けておきます。 2167|・bf2 は、Errors_printf, Errors_printf_release のバッファ(Error_log)がいっぱいに 2168| なったときだけ呼ばれます。 2169|・アセンブラデバッガでは、ブレーク中に r6 に値を入れると、その回数だけ 2170| 次のブレークを無視します。→Errors_nextBreakCount 変数 2171|****************************************************************************/ 2172|int bf( int r6, int r7, int r8, int r9 ) 2173|{ 2174| /* ブレークする */ 2175| #ifdef FOR_DOS32 2176| getch(); 2177| #endif 2178| #ifdef FOR_DOS16 2179| getch(); 2180| #endif 2181| 2182| #ifdef FOR_GHS 2183| if ( !( r6 & 0xF0000000 ) ) 2184| return r6; 2185| #endif 2186| 2187| r6,r7,r8,r9; /* avoid warning */ 2188| return 1; 2189|} 2190| 2191|void bf2( int r6, int r7, int r8, int r9 ) /* bf() と内容は同じ */ 2192|{ 2193| /* ブレークする */ 2194| #ifdef FOR_DOS32 2195| getch(); 2196| #endif 2197| #ifdef FOR_DOS16 2198| getch(); 2199| #endif 2200| 2201| r6,r7,r8,r9; /* avoid warning */ 2202|} 2203| 2204| 2205| 2206|/*************************************************************************** 2207| 6-29. <<< [Errors_break_imp] ブレークポイント >>> 2208|【引数】 2209| ・int r6; 0xBBBBBBBB=ブレーク、0xCCCCCCCC=表示なしブレーク 2210| ・int r7; ヒント数値 2211| ・int r8; ブレークしているファイル名のアドレス 2212| ・int r9; ブレークしている行番号 2213|【補足】 2214|・デバッガでは、bf(アセンブラでは _bf)にブレークポイントを付けておきます。 2215|・Error_log をファイルに出力するようになっている場合、ブレークする直前で 2216| Errors_printf_flush を実行します。 2217|****************************************************************************/ 2218|void Errors_break_imp( int r6, int r7, int r8, int r9 ) 2219|{ 2220| if ( Errors_breakFlag && ( Errors_breakID == 0 || Errors_breakID == r7 ) ) { 2221| if ( r6 != 0xCCCCCCCC ) { 2222| 2223| /* ブレーク表示する */ 2224| Errors_printf_release( "break in %s(%d) : hint = %d(0x%X)", (char*)r8, r9, r7, r7 ); 2225| ERRORS_PRINTF_FLUSH(); 2226| } 2227| Errors_breakCount ++; 2228| ASSERT( Errors_nextBreakCount > 0 ); 2229| if ( Errors_nextBreakCount == 1 ) 2230| Errors_nextBreakCount = bf( r6, r7, r8, r9 ); 2231| else 2232| Errors_nextBreakCount --; 2233| } 2234|} 2235| 2236| 2237| 2238|/*************************************************************************** 2239| 6-30. <<< [Errors_breakFlag] ブレークフラグ >>> 2240|【補足】 2241|・Errors_break コマンドによってブレークするかどうかのフラグです。 2242|・関数ツリーの深いところにあるブレークを有効にするか無効にするかを 2243| コントロールすることができます。 2244|・プログラムでフラグを変更する場合は、Errors_setBreakFlag を使ってください。 2245| デバッガで変更する場合は、Errors_breakFlag グローバル変数の値を 2246| 変更してください。 2247|****************************************************************************/ 2248|bool Errors_breakFlag = true; /* ブレークフラグ */ 2249| 2250| 2251| 2252|/*************************************************************************** 2253| 6-31. <<< ブレーク関連変数 >>> 2254| 6-32. <<< [Errors_nextBreakCount] 次にブレークするブレーク位置(個数) >>> 2255| 6-33. <<< [Errors_breakCount] ブレーク・カウンタ >>> 2256| 6-34. <<< [Errors_breakID] ブレーク番号 >>> 2257|【補足】 2258|・Errors_break, Errors_break_release で、Errors_nextBreakCount 回分 2259| 次のブレークポイントで止まるようにします。その間、bf 関数の呼び出しをしません。 2260|・Errors_breakCount は、ブレークしたらカウントアップします。 2261| ブレークポイント A から B までの間をスキップする場合は、 2262| A でブレークしているときに、 Errors_nextBreakCount(bf関数のr6)に 2263| (B のカウント)-(A のカウント)を設定します。 2264|****************************************************************************/ 2265|int Errors_nextBreakCount = 1; 2266|int Errors_breakCount = 0; 2267|int Errors_breakID = 0; /* Errors_setBreakID マクロを参照 */ 2268| 2269| 2270|/*************************************************************************** 2271| 6-35. <<< [Errors_X, Errors_X2, Errors_X3] デバッグ用パラメータ >>> 2272|【補足】 2273|・これらの変数は、再コンパイルしないでパラメータを変化させるときに 2274| 使います。 2275|・ERRORS_CUT_DEBUG_TOOL を #define すると使用できなくなります。 2276|****************************************************************************/ 2277|#ifndef ERRORS_CUT_DEBUG_TOOL 2278| int Errors_X = 0; 2279| int Errors_X2 = 1; 2280| int Errors_X3 = 2; 2281| int Errors_Line = 0; 2282|#endif 2283| 2284| 2285|/*--------------------------------------------------------------------*/ 2286|/* 7. <<<<◆ 関数コール履歴 >>>> */ 2287|/*--------------------------------------------------------------------*/ 2288| 2289| 2290|#if ! defined(ERRORS_CUT_DEBUG_TOOL) && defined(ERRORS_USE_FUNCLOG) 2291| 2292|bool Errors_FuncLog_inited = false; 2293|Errors_FuncLog Errors_FuncLog_globl; 2294| 2295| 2296|/*************************************************************************** 2297| 7-1. <<< [Errors_FuncLog_init] 関数コール履歴の初期化 >>> 2298|****************************************************************************/ 2299|void Errors_FuncLog_init( Errors_FuncLog* m ) 2300|{ 2301| Errors_FuncLog_inited = true; 2302| m->funcs_n = 0; 2303| m->bLongJumped = false; 2304|} 2305| 2306| 2307|/*************************************************************************** 2308| 7-2. <<< [Errors_FuncLog_print_imp] Errors_FuncLog_print の関数部分 >>> 2309|****************************************************************************/ 2310|void Errors_FuncLog_print_imp( Errors_FuncLog* m ) 2311|{ 2312| Errors_FuncLog_Elem* p; 2313| Errors_FuncLog_Elem* p_over; 2314| 2315| if ( ! Errors_FuncLog_inited ) 2316| error2_0( Errors_Err_FuncLogNotInit, "Errors_FuncLog_init を呼び出していません" ); 2317| 2318| Errors_printf( "Func Call Stack ..." ); 2319| 2320| p_over = &m->funcs[m->funcs_n]; 2321| for ( p = &m->funcs[0]; p < p_over; p++ ) { 2322| Errors_printf( " %s()", p->name ); 2323| } 2324|} 2325| 2326| 2327| 2328|/*************************************************************************** 2329| 7-3. <<< [Errors_FuncLog_onLongJump] ロングジャンプしたときの処理 >>> 2330|****************************************************************************/ 2331|void Errors_FuncLog_onLongJump( Errors_FuncLog* m ) 2332|{ 2333| m->bLongJumped = true; 2334|} 2335| 2336| 2337| 2338|/*************************************************************************** 2339| 7-4. <<< [Errors_FuncLog_setStart] ERRORS_FUNC_START の関数部分 >>> 2340|****************************************************************************/ 2341|void Errors_FuncLog_setStart( Errors_FuncLog* m, void* func, char* func_name ) 2342|{ 2343| #ifdef ERRORS_FUNCLOG_LED 2344| LED7_outNum( ERRORS_FUNCLOG_LED, 2 ); 2345| #else 2346| if ( ! Errors_FuncLog_inited ) 2347| error2_0( Errors_Err_FuncLogNotInit, "Errors_FuncLog_init を呼び出していません" ); 2348| 2349| #ifdef ERRORS_FUNCLOG_PRINT_EVERY 2350| Errors_printf( "%s() start", func_name ); 2351| if ( Errors_WATCH_adr != NULL ) WATCH(); 2352| #endif 2353| 2354| if ( m->bLongJumped ) { 2355| int i; 2356| 2357| m->bLongJumped = false; 2358| for ( i = 0; i < Errors_FuncLog_size; i++ ) { 2359| if ( m->funcs[i].adr == func ) { 2360| m->funcs_n = i + 1; 2361| return; 2362| } 2363| } 2364| m->funcs_n = 0; 2365| } 2366| 2367| if ( m->funcs_n == Errors_FuncLog_size ) return; 2368| 2369| m->funcs[m->funcs_n].adr = func; 2370| m->funcs[m->funcs_n].name = func_name; 2371| m->funcs_n++; 2372| #endif 2373|} 2374| 2375| 2376| 2377|/*************************************************************************** 2378| 7-5. <<< [Errors_FuncLog_setEnd] ERRORS_FUNC_END の関数部分 >>> 2379|****************************************************************************/ 2380|void Errors_FuncLog_setEnd( Errors_FuncLog* m, void* func, char* func_name ) 2381|{ 2382| #ifdef ERRORS_FUNCLOG_LED 2383| LED7_outNum( ERRORS_FUNCLOG_LED, 4 ); 2384| #else 2385| Errors_FuncLog_Elem* p; 2386| Errors_FuncLog_Elem* p_first; 2387| 2388| if ( ! Errors_FuncLog_inited ) 2389| error2_0( Errors_Err_FuncLogNotInit, "Errors_FuncLog_init を呼び出していません" ); 2390| 2391| #ifdef ERRORS_FUNCLOG_PRINT_EVERY 2392| Errors_printf( "%s() end", func_name ); 2393| if ( Errors_WATCH_adr != NULL ) WATCH(); 2394| #endif 2395| 2396| p_first = &m->funcs[0]; 2397| for ( p = &m->funcs[m->funcs_n - 1]; p >= p_first; p-- ) { 2398| if ( p->adr == func ) { m->funcs_n = p - p_first; return; } 2399| } 2400| Errors_printf( "Not find in FuncLog! Not match START/END or longjumped" ); 2401| #endif 2402|} 2403| 2404| 2405| 2406|#endif /* ERRORS_CUT_DEBUG_TOOL, ERRORS_USE_FUNCLOG */ 2407| 2408|