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