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_nextBreakCount(bf関数の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|