EXCEPT2.H
[目次 | 型・クラス・構造体 | マクロ]
- 1. 例外処理シミュレート2 (Except2)
- 2. queue
- 3. モジュール・プロパティ
- 4. 優先ヘッダ
- 5. モジュール設定
- 6. Interface Area ----------------------------------------
- 7. 例外メッセージ・インターフェイス [Except2]
- 8. 標準・例外メッセージ [Except2_Std]
- 9. 文字列・例外メッセージ [Except2_Str]
- 10. ファイル・例外メッセージ [Except2_File]
- 11. 例外メッセージ・実装サンプル [Sample_Except2]
- 12. 例外処理システム [Except2_Sys] ★
- 13. Mapping Area ------------------------------------------
- 14. ◆例外メッセージ・インターフェイス (Except2)
- 15. ◆標準・例外メッセージ (Except2_Std)
- 16. ◆文字列・例外メッセージ (Except2_Str)
- 17. ◆例外処理システム (Except2_Sys)
- 18. デバッグ用エラー処理ハンドラを登録する [Except2_Sys_setErrorHandler]
- 19. デバッグ用例外処理ハンドラを登録する [Except2_Sys_setExceptHandler]
- 20. ユーザ・エラーかどうか [Except2_Sys_isUserError]
- 21. try ブロック [try, c_try]
- 22. catch ブロック [catch, catch_Except2, catch_xxx, end_catch]
- 23. [c_catch, c_catch_Except2, c_catch_xxx, c_end_catch]
- 24. finally ブロック [finally, end_finally, c_finally, c_end_finally]
- 25. throw [throw, throw_again, c_throw, c_throw_again]
1|/*************************************************************************
2|* 1. <<< 例外処理シミュレート2 (Except2) >>>
3|*
4|*・例外処理をするブロックの記述例
5|* try { // try ブロック
6|* foo();
7|* }
8|* catch_Except2( msg ) { // catch ブロック
9|* Except2_Sys_print(); // デフォルトのエラー状況を表示する
10|* throw( msg ); // 例外を再び投げることも可能
11|* } end_catch; // end_catch が必要です
12|*
13|*・例外を投げるときの記述例
14|* throw( Master_Except2_newExcept2( Master_error ) );
15|* [注意] try ブロック内で throw することはできません。
16|*
17|* 2. <<< queue >>>
18|*・try1, try2 で、catch2 したとき try3 でなく 再び try2 する
19|*・set_terminate 構文
20|**************************************************************************/
21|
22|#ifndef __EXCEPT2_H
23|#define __EXCEPT2_H
24|
25|
26|
27|/*************************************************************************
28|* 3. <<< モジュール・プロパティ >>>
29|**************************************************************************/
30|
31|/*----------------------------------------------------------------------
32|[Module Property]
33|name = Except2
34|title = 例外処理v2
35|category = エラー処理
36|src = except2.c
37|depend =
38|priority =
39|accord =
40|----------------------------------------------------------------------*/
41|/* depend = Types, Inf, StdLibs, Errors */
42|
43|
44|/*************************************************************************
45|* 4. <<< 優先ヘッダ >>>
46|**************************************************************************/
47|
48|#ifndef USES_PRIORITY_HEADER
49|/*[START_OF_PRIORITY_HEADER]*/
50|
51|#define USES_EXCEPT2
52|INF_TYPEDEF( _Except2, Except2 );
53|typedef struct _Except2_Std Except2_Std;
54|typedef struct _Except2_Str Except2_Str;
55|typedef struct _Except2_File Except2_File;
56|typedef struct _Except2_Sys Except2_Sys;
57|
58|#define Except2_Err_BufFull (221)
59|
60|#ifndef STDLIBS_INCLUDE_SETJMP_H
61| #define STDLIBS_INCLUDE_SETJMP_H
62|#endif
63|#ifdef FOR_WIN32
64| #ifndef STDLIBS_INCLUDE_STDLIB_H
65| #define STDLIBS_INCLUDE_STDLIB_H
66| #endif
67|#endif
68|#ifdef FOR_DOS32
69| #ifndef STDLIBS_INCLUDE_STDLIB_H
70| #define STDLIBS_INCLUDE_STDLIB_H
71| #endif
72|#endif
73|
74|/*[END_OF_PRIORITY_HEADER]*/
75|#endif /* USES_PRIORITY_HEADER */
76|
77|
78|
79|/*************************************************************************
80|* 5. <<< モジュール設定 >>>
81|**************************************************************************/
82|#ifndef EXCEPT2_SETTING
83|
84| /* EXCEPT2_NOMSG : Except2_Std 型のエラーメッセージを省略する */
85| #ifdef NDEBUG
86| #define EXCEPT2_NOMSG
87| #endif
88| #if defined(ERRORS_ASSERT_REPORT) || defined(ERRORS_ERROR_REPORT)
89| #ifdef EXCEPT2_NOMSG
90| #undef EXCEPT2_NOMSG
91| #endif
92| #endif
93|#endif
94|
95|
96|
97|
98|/*-----------------------------------------------------------------*/
99|/* 6. <<< Interface Area ---------------------------------------- >>> */
100|/*-----------------------------------------------------------------*/
101|
102|#ifdef __cplusplus
103|extern "C" {
104|#endif
105|
106|
107|/*************************************************************************
108|* 7. <<< 例外メッセージ・インターフェイス [Except2] >>>
109|*【補足】
110|*・このインターフェイス・クラスの実装の仕方は、後記の Sample_Except2 を
111|* 参考にしてください。
112|**************************************************************************/
113|INF_DECLARE_START( _Except2, Except2 )
114|INF_DECLARE_METHOD_0( void, _delete, Except2 )
115|INF_DECLARE_METHOD_1( bool, isType, Except2,char* )
116|INF_DECLARE_METHOD_0( char*, print, Except2 )
117|INF_DECLARE_END();
118|
119|void Except2_delete( Except2 );
120|bool Except2_isType( Except2, char* type );
121|char* Except2_print( Except2 );
122|
123|
124|
125|/*************************************************************************
126|* 8. <<< 標準・例外メッセージ [Except2_Std] >>>
127|*【役割】
128|*・エラーコードとエラーメッセージ扱う標準的な例外(エラー)です。
129|*・エラーメッセージを省略してプログラムサイズを小さくすることが出来ます。
130|* (→EXCEPT2_NOMSGマクロ)
131|**************************************************************************/
132|struct _Except2_Std {
133| int code; /* エラーコード */
134| #ifndef EXCEPT2_NOMSG
135| char codeStr[256]; /* エラーコードのマクロ名 */
136| char msg[256]; /* エラーメッセージ */
137| #endif
138|};
139|Except2 Except2_Std_newExcept2( int code, const char* msg );
140|Except2 Except2_Std_newExcept2_f( int code, const char* fmt, ... );
141|Except2 Except2_Std_newExcept2_c( int code, const char* codeStr,
142| const char* msg );
143|Except2 Except2_Std_newExcept2_cf( int code, const char* codeStr,
144| const char* fmt, ... );
145|void Except2_Std_delete( Except2_Std* );
146|bool Except2_Std_isType( Except2_Std*, char* type );
147|char* Except2_Std_print( Except2_Std* );
148|int Except2_Std_sprint( Except2_Std*, char* s );
149|
150|/* 内部用 */
151|Except2 Except2_Std_inf_Except2( Except2_Std* );
152|Except2_Std* Except2_Std_by_Except2( Except2 );
153|
154|
155|
156|/*************************************************************************
157|* 9. <<< 文字列・例外メッセージ [Except2_Str] >>>
158|*【役割】
159|*・文字列メッセージを格納する例外メッセージです。
160|*・エラーの体系が整っていない場合に用います。
161|**************************************************************************/
162|struct _Except2_Str {
163| char errorMsg[256];
164|};
165|Except2 Except2_Str_newExcept2( const char* msg );
166|Except2 Except2_Str_newExcept2_f( const char* fmt, ... );
167|void Except2_Str_delete( Except2_Str* );
168|bool Except2_Str_isType( Except2_Str*, char* type );
169|char* Except2_Str_print( Except2_Str* );
170|
171|/* 内部用 */
172|Except2 Except2_Str_inf_Except2( Except2_Str* );
173|Except2_Str* Except2_Str_by_Except2( Except2 );
174|
175|
176|
177|#ifndef FOR_NOFILE
178|/*************************************************************************
179|* 10. <<< ファイル・例外メッセージ [Except2_File] >>>
180|*【役割】
181|*・ファイルに関する一般的な例外メッセージです。
182|**************************************************************************/
183|struct _Except2_File {
184| char fname[_MAX_PATH]; /* 相対ファイルパス */
185| char fullpath[_MAX_PATH]; /* 絶対ファイルパス */
186| int errorCode;
187|};
188|Except2 Except2_File_newExcept2( const char* fname, int errorCode );
189|void Except2_File_delete( Except2_File* );
190|bool Except2_File_isType( Except2_File*, char* type );
191|char* Except2_File_print( Except2_File* );
192|
193|#define Except2_File_CannotReadOpen 0
194|#define Except2_File_CannotWriteOpen 1
195|#define Except2_File_EOF 2
196|#define Except2_File_BadFormat 3
197|
198|
199|/* 内部用 */
200|Except2 Except2_File_inf_Except2( Except2_File* );
201|Except2_File* Except2_File_by_Except2( Except2 );
202|
203|#endif /* not FOR_NOFILE */
204|
205|
206|
207|/*************************************************************************
208|* 11. <<< 例外メッセージ・実装サンプル [Sample_Except2] >>>
209|*
210|*・エラーコードを1つだけ持つ例外メッセージを例に、例外メッセージの
211|* 実装例を示します。そのまま、コピーすれば使用できますが、修正が
212|* 必要になる個所には [imp] マークを付けています。
213|*
214|*・メンバ変数は、次のようにします。
215|* struct _Sample_Except2 {
216|* int errorCode; // エラーコード
217|* // [imp] その他、エラー処理に必要な変数を並べる。(通常は要らない)
218|* };
219|*
220|*・一般的な例外メッセージクラスのインターフェイスは、次の通りです。
221|* delete と print は、Except2 インターフェイスから継承しています。
222|* Except2 Sample_Except2_newExcept2( int errorCode ); // [imp]
223|* void Sample_Except2_delete( Sample_Except2* );
224|* void Sample_Except2_print( Sample_Except2* );
225|* Except2 Sample_Except2_inf_Except2( Sample_Except2* ); // 内部用
226|*
227|*・インターフェイス・コンストラクタ Sample_Except2_newExcept2 は、
228|* 次のようにします。通常のコンストラクタと異なり、Except2 インター
229|* フェイスを返します。
230|* Except2 Sample_Except2_newExcept2( int errorCode )
231|* {
232|* static Sample_Except2 ex; // 静的領域に確保する
233|*
234|* ex.errorCode = errorCode;
235|* // [imp] その他 メンバ変数の設定
236|*
237|* return Sample_Except2_inf_Except2( &ex );
238|* }
239|*
240|*・デストラクタ Sample_Except2_delete は、catch ブロックから抜けるときに
241|* 行う処理を記述します。通常は、何も無くてよいですが、関数の実体は
242|* 作っておいてください。
243|* void Sample_Except2_delete( Sample_Except2* this )
244|* {
245|* // [imp] 後始末処理
246|* }
247|*
248|*・型チェック関数 Sample_Except2_isType は、次のようにします。
249|* bool Sample_Except2_isType( Sample_Except2* this, char* type )
250|* {
251|* return ( strcmp( type, "Sample_Except2*" ) == 0 );
252|* }
253|*
254|*・エラー状況表示関数 Sample_Except2_print は、次のようにします。
255|* void Sample_Except2_print( Sample_Except2* this )
256|* {
257|* char* msg;
258|*
259|* switch( this->errorCode ) {
260|* case 1: msg = "out of memory"; break;
261|* // [imp]
262|* }
263|* printf( "ERROR : %s\n", msg );
264|* }
265|*
266|*・例外メッセージのインターフェイスを返す関数は、次のようにします。
267|* 関数名を修正して、そのまま利用できます。
268|* Except2 Sample_Except2_inf_Except2( Sample_Except2* this )
269|* {
270|* static Except2_Sc sc;
271|* static int initialized = 0;
272|* Except2 inf;
273|*
274|* if ( ! initialized ) {
275|* sc._delete = Sample_Except2_delete; // delete 関数
276|* sc.print = Sample_Except2_print; // print 関数
277|* initialized = 1;
278|* };
279|* inf.sc = ≻
280|* inf.obj = this;
281|*
282|* return inf;
283|* }
284|***************************************************************************/
285|
286|
287|
288|/*************************************************************************
289|* 12. <<< 例外処理システム [Except2_Sys] ★>>>
290|**************************************************************************/
291|#define Except2_Sys_mTry 10 /* try のネスト数の最大 */
292|#define Except2_Sys_mThrow 10 /* 再 throw の回数の最大+1 */
293|struct _Except2_Sys {
294| jmp_buf longjmp_buf[Except2_Sys_mTry]; /*ジャンプ*/
295| Except2 msg; /* 例外メッセージのインターフェイス */
296| bool msg_bExist; /* msg が有効かどうか */
297| bool msg_bCatch; /* msg を catch したかどうか */
298| bool msg_bAgain; /* msg を再 throw 中かどうか(2つの経路がある) */
299| char* try_file[Except2_Sys_mTry]; /* try ブロック開始ファイル名 */
300| int try_line[Except2_Sys_mTry]; /* try ブロック開始行番号 */
301| int nTry; /* try ブロックのネスト数 */
302| char* throw_file[Except2_Sys_mThrow]; /* 例外が発生したファイル名 */
303| int throw_line[Except2_Sys_mThrow]; /* 例外が発生した行番号 */
304| int nThrow; /* 例外の発生数 */
305| char* catch_file; /* 最後に例外をキャッチしたファイル名 */
306| int catch_line; /* 最後に例外をキャッチした行番号 */
307| #ifdef USES_ERRORS
308| Errors_Handler errHdl; /* エラー発生時のコールバック関数(NULL=未登録)*/
309| Errors_Handler excepHdl; /* 例外発生時のコールバック関数(NULL=未登録)*/
310| #endif
311|};
312|extern Except2_Sys Except2_sys; /* 静的変数 singleton pattern */
313|
314|/* 公開関数 */
315|void Except2_Sys_print(void);
316|bool Except2_Sys_isExistMsg(void);
317|void Except2_Sys_setErrorHandler( Errors_Handler );
318|void Except2_Sys_setExceptHandler( Errors_Handler );
319|bool Except2_Sys_isUserError(void);
320|
321|/* 内部用 */
322|int Except2_Sys_try_imp( char* file, int line );
323|int Except2_Sys_catch_imp( char* className, char* file, int line );
324|void Except2_Sys_end_finally_imp(void);
325|void Except2_Sys_throw_imp( Except2, char* file, int line );
326|
327|#ifdef __cplusplus
328|}
329|#endif
330|
331|
332|/*-----------------------------------------------------------------*/
333|/* 13. <<< Mapping Area ------------------------------------------ >>> */
334|/*-----------------------------------------------------------------*/
335|
336|
337|
338|/*-----------------------------------------------------------------*/
339|/* 14. <<< ◆例外メッセージ・インターフェイス (Except2) >>> */
340|/*-----------------------------------------------------------------*/
341|
342|#ifdef NDEBUG
343|#define Except2_delete(t) INF_MACRO_0( Except2, _delete, void, Except2_delete, Except2,t )
344|#define Except2_isType(t,a) INF_MACRO_1( Except2, isType, bool, Except2_isType, Except2,char*,t,a )
345|#define Except2_print(t) INF_MACRO_0( Except2, print, void, Except2_print, Except2,t )
346|#endif
347|
348|
349|
350|/*-----------------------------------------------------------------*/
351|/* 15. <<< ◆標準・例外メッセージ (Except2_Std) >>> */
352|/*-----------------------------------------------------------------*/
353|
354|#ifdef NDEBUG
355|#define Except2_Std_by_Except2(inf) (Except2_Std*)(inf).obj /*INF_SUB_MACRO( Except2_Std, Except2, Except2_Std_by_Except2 )*/
356|#endif
357|
358|
359|
360|/*-----------------------------------------------------------------*/
361|/* 16. <<< ◆文字列・例外メッセージ (Except2_Str) >>> */
362|/*-----------------------------------------------------------------*/
363|
364|#ifdef NDEBUG
365|#define Except2_Str_by_Except2(inf) INF_SUB_MACRO( Except2_Str, Except2, Except2_Str_by_Except2 )
366|#endif
367|
368|
369|
370|/*-----------------------------------------------------------------*/
371|/* 17. <<< ◆例外処理システム (Except2_Sys) >>> */
372|/*-----------------------------------------------------------------*/
373|
374|
375|/*************************************************************************
376|* 18. <<< デバッグ用エラー処理ハンドラを登録する [Except2_Sys_setErrorHandler] >>>
377|*【機能】
378|*・最も上のレベルの try ブロック内の throw 文を実行したときに呼び出される関数を
379|* 登録します。
380|*【補足】
381|*・本ハンドラは、全体で1つしか登録できないのでデバッグ用に用いてください。
382|* (本関数を使うところの近くに #ifdef NDEBUG 〜 #error を置くとよいでしょう)
383|* リリース版では、正式な例外処理構文(try〜catch)を用いてください。
384|* Errors_setHandler と同じところに登録するので注意してください。
385|*・例外処理ハンドラの関数の型については、Errors_Handler 型の解説を
386|* 参照してください。
387|**************************************************************************/
388|#define Except2_Sys_setErrorHandler( hdl ) Except2_sys.errHdl = (hdl)
389|
390|
391|/*************************************************************************
392|* 19. <<< デバッグ用例外処理ハンドラを登録する [Except2_Sys_setExceptHandler] >>>
393|*【機能】
394|*・throw 文を実行したときに呼び出される関数を登録します。
395|*【補足】
396|*・try ブロックが重なっている場合、再スローするたびに登録された関数が
397|* 呼び出されます。
398|*・本ハンドラは、全体で1つしか登録できないのでデバッグ用に用いてください。
399|* (本関数を使うところの近くに #ifdef NDEBUG 〜 #error を置くとよいでしょう)
400|* リリース版では、正式な例外処理構文(try〜catch)を用いてください。
401|*・例外処理ハンドラの関数の型は、エラー処理ハンドラ(→Except2_Sys_setErrorHandler)
402|* と同じですが、返り値を ERRORS_IGNORE にすると、例外を投げます。
403|**************************************************************************/
404|#define Except2_Sys_setExceptHandler( hdl ) Except2_sys.excepHdl = (hdl)
405|
406|
407|/*************************************************************************
408|* 20. <<< ユーザ・エラーかどうか [Except2_Sys_isUserError] >>>
409|*【機能】
410|*・ユーザの ASSERT または、try ブロックの外の ASSERT かどうか判定します。
411|*【補足】
412|*・エラー処理ハンドラの返り値として、ユーザ・エラーなら ERRORS_EXIT、
413|* ライブラリ内部のエラーなら ERRORS_IGNORE とするときに用います。
414|**************************************************************************/
415|#define Except2_Sys_isUserError() \
416| (Except2_sys.nTry < Except2_sys.nThrow)
417|
418|
419|
420|/*************************************************************************
421|* 21. <<< try ブロック [try, c_try] >>>
422|*【補足】
423|*・全体は「try 〜 catch ブロックのマクロの展開内容」を参照。
424|**************************************************************************/
425|#define c_try \
426| if ( setjmp( Except2_sys.longjmp_buf[Except2_sys.nTry] ) == 0 ) { \
427| Except2_Sys_try_imp( __FILE__, __LINE__ ); {
428|
429|#define try c_try
430|
431|/*************************************************************************
432|* 22. <<< catch ブロック [catch, catch_Except2, catch_xxx, end_catch] >>>
433|* 23. <<< [c_catch, c_catch_Except2, c_catch_xxx, c_end_catch] >>>
434|*【補足】
435|*・type には、ポインタ型を指定してください。
436|*・arg には、変数名を指定してください。arg は、type に関係無く Except2 型です。
437|*・catch ( ... ) 構文は catch_xxx () としてください。
438|*・catch ( Except2, msg ) は catch_Except2 ( msg ) としてください。
439|*・catch ブロック内で break や return や goto を使わないでください。
440|*・全体は「try 〜 catch ブロックのマクロの展開内容」を参照。
441|*【例】
442|* catch ( Some_Except*, msg ){
443|* Some_Except_print( msg ); // msg は、Some_Except* 型です
444|* }
445|* catch_Except2 ( msg ){
446|* Except2_print( msg ); // msg は、Except2 型です
447|* } end_catch;
448|* catch_xxx (){
449|* Except2_Sys_print(); // msg はありません
450|* } end_catch;
451|**************************************************************************/
452|#define c_catch( type, arg ) \
453| } } else if ( Except2_Sys_catch_imp( #type, __FILE__, __LINE__ ) ) \
454| { type arg = (type)Except2_sys.msg.obj; \
455| {
456|
457|#define c_catch_Except2( arg ) \
458| } } else if ( Except2_Sys_catch_imp( "...", __FILE__, __LINE__ ) ) \
459| { Except2 arg = Except2_sys.msg; \
460| {
461|
462|#define c_catch_xxx() \
463| } } else if ( Except2_Sys_catch_imp( "...", __FILE__, __LINE__ ) ) \
464| { {
465|
466|#define c_end_catch \
467| finally{ }end_finally \
468|
469|
470|#define catch c_catch
471|#define catch_Except2 c_catch_Except2
472|#define catch_xxx c_catch_xxx
473|#define end_catch c_end_catch
474|
475|
476|/*************************************************************************
477|* 24. <<< finally ブロック [finally, end_finally, c_finally, c_end_finally] >>>
478|*【補足】
479|*・すべての catch ブロックの後に記述してください。
480|*・end_catch の代わりに end_finally を記述してください。
481|*・全体は「try 〜 catch ブロックのマクロの展開内容」を参照。
482|*【例】
483|* finally {
484|* if ( obj != NULL ) Obj_finish( obj );
485|* } end_finally;
486|**************************************************************************/
487|#define c_finally \
488| } } \
489| {
490|
491|#define c_end_finally \
492| } \
493| Except2_Sys_end_finally_imp();
494|
495|
496|#define finally c_finally
497|#define end_finally c_end_finally
498|
499|
500|/*************************************************************************
501|* 25. <<< throw [throw, throw_again, c_throw, c_throw_again] >>>
502|*【引数】
503|* ・Except2 msg; 例外メッセージ
504|*【補足】
505|*・再スローするときは、throw_again(); としますが、throw(msg) でも構いません。
506|*・msg には、たとえば、Sample_Except2 クラスの Sample_Except2_newExcept2
507|* 関数の返り値を指定します。
508|*・引数は、Except2 型のみです。
509|*・throw に対するキャッチが無い場合、デフォルトのエラーメッセージを表示します。
510|*・全体は「try 〜 catch ブロックのマクロの展開内容」を参照。
511|**************************************************************************/
512|#define c_throw(msg) \
513| Except2_Sys_throw_imp( (msg), __FILE__, __LINE__ )
514|
515|#define c_throw_again() \
516| Except2_Sys_throw_imp( Except2_sys.msg, __FILE__, __LINE__ )
517|
518|#define throw c_throw
519|#define throw_again c_throw_again
520|
521|
522|#endif /* __EXCEPT2_H */
523|
524|