EXCEPT3.H
[目次 | 型・クラス・構造体 | マクロ]
1|/*************************************************************************
2|* 1. <<< ソフトウェア例外処理3 (Except3) >>>
3|**************************************************************************/
4|
5|#ifndef __EXCEPT3_H
6|#define __EXCEPT3_H
7|
8|#ifdef count
9| #undef count
10|#endif
11|
12|/*************************************************************************
13|* 2. <<< モジュール・プロパティ >>>
14|**************************************************************************/
15|
16|/*----------------------------------------------------------------------
17|[Module Property]
18|name = Except3
19|title = 例外処理v3
20|category = エラー処理
21|src = except3.c
22|depend =
23|priority =
24|accord =
25|----------------------------------------------------------------------*/
26|/* depend = Types, Inf, StdLibs, Errors */
27|
28|
29|/*************************************************************************
30|* 3. <<< 優先ヘッダ >>>
31|**************************************************************************/
32|
33|#ifndef USES_PRIORITY_HEADER
34|/*[START_OF_PRIORITY_HEADER]*/
35|
36|#define USES_EXCEPT3
37|typedef struct _Except3 Except3;
38|typedef struct _Except3_Try Except3_Try;
39|#ifdef USES_INF
40| INF_TYPEDEF( _Except3_MsgStack, Except3_MsgStack );
41|#endif
42|
43|#define STDLIBS_INCLUDE_SETJMP_H
44|
45|#define Except3_Err_NoInit (5282) /* 初期化していない */
46|#define Except3_Err_OutOfTry (5283) /* 例外メッセージが try ブロックの外に出た */
47|#define Except3_Err_TryStackOver (5284) /* try ブロックのスタックがオーバーした */
48|#define Except3_Err_DupTry (5285) /* catch, finally 内で try された */
49|#define Except3_Err_FinallyThrow (5286) /* finally 内で throw された */
50|
51|/*[END_OF_PRIORITY_HEADER]*/
52|#endif /* USES_PRIORITY_HEADER */
53|
54|
55|
56|/*************************************************************************
57|* 4. <<< モジュール設定 >>>
58|**************************************************************************/
59|#ifndef EXCEPT3_SETTING
60|#define EXCEPT3_SETTING
61|
62| /* #define EXCEPT3_NO_EXIT_CHK */ /* 異常終了時に後始末チェックを行わない */
63|
64|#endif
65|
66|#ifdef ERRORS_NO_EXIT_CHK
67| #define EXCEPT3_NO_EXIT_CHK
68|#endif
69|
70|
71|
72|/*-----------------------------------------------------------------*/
73|/* 5. <<< Interface Area ---------------------------------------- >>> */
74|/*-----------------------------------------------------------------*/
75|
76|#ifdef __cplusplus
77|extern "C" {
78|#endif
79|
80|
81|/*************************************************************************
82|* 6. <<< [Except3] ソフトウェア例外処理3 >>>
83|*【補足】
84|*・本クラスは try, catch, throw などから適宜使用されます。
85|*・main 関数の最初(各タスクのスタートアップ)で Except3_init を
86|* 実行してください。
87|*・Except3_Try::bNoJumpAreaTop は、ロングジャンプしない領域のトップの
88|* try ブロックかどうかです。
89|**************************************************************************/
90|
91|void Except3_init( Except3_Try* trys, int trys_size );
92|/* void Except3_initEasy( errName ); */
93|/* EXCEPT3_DECLARE_EASY_ERROR_HANDLER( errName ); */
94|/* c_try {} */
95|/* c_catch( type, arg ) {} */
96|/* c_finally {} */
97|/* c_end_finally; */
98|/* c_throw( void* ); */
99|/* c_throw_again(); */
100|/* c_if_error { } c_then { } c_endif; */
101|void Except3_startNoJumpArea(void);
102|void Except3_endNoJumpArea(void);
103|bool Except3_isNoJumpArea(void);
104|bool Except3_isError(void);
105|bool Except3_isDblError(void);
106|int Except3_getErrorCode(void);
107|void Except3_print(void);
108|
109|
110|#define Except3_m 3 /* システム数(=タスク数) */
111|
112|struct _Except3 {
113| void* msg; /* エラーメッセージのアドレス */
114| bool bExcept; /* 例外発生中かどうか */
115| bool bAgain; /* 再スロー中(finally)かどうか */
116| bool bCatch; /* キャッチしたかどうか */
117| bool bNoJumpArea; /* ロングジャンプしない領域内かどうか */
118| int nTry; /* try ブロックのネスト数 */
119| int mTry; /* try ブロックのネスト数の最大 */
120| Except3_Try* tryInfo; /* tryInfo のメモリ領域 */
121| ERRORS_INITCHK_VAR
122|};
123|struct _Except3_Try {
124| jmp_buf longjmp_buf; /* ロング・ジャンプ */
125| bool bNoJumpAreaTop; /* →補足 */
126| char* file; /* try ブロック開始ファイル名 */
127| int line; /* try ブロック開始行番号 */
128|};
129|
130|
131|#ifdef USES_MULTASK
132| extern Except3 Except3_con[Except3_m];
133|#else
134| extern Except3 Except3_con;
135|#endif
136|
137|/* 内部用 */
138|void Except3_init_imp( Except3*, Except3_Try*, int );
139|void Except3_try_imp( Except3*, char* file, int line );
140|int Except3_catch_imp( Except3* );
141|void Except3_end_finally_imp( Except3* );
142|void Except3_throw_imp( Except3*, void* );
143|void Except3_startNoJumpArea_imp( Except3* );
144|void Except3_endNoJumpArea_imp( Except3* );
145|bool Except3_isNoJumpArea_imp( Except3* );
146|bool Except3_isError_imp( Except3* );
147|void Except3_print_imp( Except3* );
148|void Except3_error_imp( int code, const char* msg, char* file, int line );
149|
150|
151|/*************************************************************************
152|* 7. <<< [Except3_MsgStack] メッセージ・スタック抽象型 >>>
153|**************************************************************************/
154|#ifdef USES_INF
155|void* Except3_MsgStack_push( Except3_MsgStack, void* msg );
156|void* Except3_MsgStack_pop( Except3_MsgStack, void* msg );
157|
158|struct _Except3_MsgStack_Sc {
159| void* (*push)( void* obj, void* elem );
160| void* (*pop)( void* obj, void* elem );
161|};
162|
163|#ifdef NDEBUG
164|#define Except3_MsgStack_push(t,a) INF_MACRO_1( Except3_MsgStack, push, void*, Except3_MsgStack_push, Except3_MsgStack,void*,t,a )
165|#define Except3_MsgStack_pop(t,a) INF_MACRO_1( Except3_MsgStack, pop, void*, Except3_MsgStack_pop, Except3_MsgStack, int, char*,t,a )
166|#endif
167|
168|#endif
169|
170|#ifdef __cplusplus
171|}
172|#endif
173|
174|/*-----------------------------------------------------------------*/
175|/* 8. <<< Mapping Area ------------------------------------------ >>> */
176|/*-----------------------------------------------------------------*/
177|
178|
179|
180|/*--------------------------------------------------------------------*/
181|/* 9. <<<◆(Except3) 例外処理システム >>> */
182|/*--------------------------------------------------------------------*/
183|
184|/*************************************************************************
185|* 10. <<< [Except3_init] 例外処理システムの初期化 >>>
186|**************************************************************************/
187|#ifdef USES_MULTASK
188|
189| #define Except3_init( tryInfo, tryInfo_size ) \
190| Except3_init_imp( &Except3_con[MulTask_Sys_getCurIndex()], \
191| tryInfo, tryInfo_size )
192|
193|#else
194|
195| #define Except3_init( tryInfo, tryInfo_size ) \
196| Except3_init_imp( &Except3_con, \
197| tryInfo, tryInfo_size )
198|
199|#endif
200|
201|
202|
203|/***********************************************************************
204|* 11. <<< [Except3_initEasy] 簡易的に例外処理システムを初期化する >>>
205|*【引数】
206|* ・errName; エラーハンドラの名前
207|*【補足】
208|*・プログラムの開始時に呼び出してください。
209|*・try の深さは固定です。変えるときは Except3_init を使用してください。
210|*・errName に指定するエラーハンドラは、EXCEPT3_DECLARE_EASY_ERROR_HANDLER
211|* を使って簡易的に定義することができます。
212|************************************************************************/
213|#define Except3_initEasy( errName ) \
214| { \
215| static Errors_Msg msgs[5]; \
216| static Except3_Try trys[10]; \
217| \
218| Errors_MsgPool_init( Errors_MsgPool_getGlobl(), msgs, sizeof(msgs) ); \
219| Except3_init( trys, sizeof(trys) ); \
220| Errors_setErrorHandler( errName ); \
221| }
222|
223|/***********************************************************************
224|* 12. <<< [EXCEPT3_DECLARE_EASY_ERROR_HANDLER] 簡易エラーハンドラを定義する >>>
225|*【引数】
226|* ・errName; エラーハンドラの名前
227|*【補足】
228|*・グローバル領域に次のような記述をすると、err というエラーハンドらが定義されます。
229|* EXCEPT3_EASY_ERROR_HANDLER( err ) (セミコロンは無し)
230|************************************************************************/
231|#define EXCEPT3_DECLARE_EASY_ERROR_HANDLER( errName ) \
232| int errName( int id, int code, char* msg ) \
233| { \
234| if ( code != Errors_ASSERT && code != Except3_Err_OutOfTry ) \
235| c_throw( Errors_Msg_getGlobl() ); \
236| \
237| id, msg; \
238| \
239| return ERRORS_EXIT; \
240| }
241|
242|
243|/*************************************************************************
244|* 13. <<< [EXCEPT3_INITCHK] Except3 用初期化チェック >>>
245|*【補足】
246|*・内部用です。
247|**************************************************************************/
248|#ifdef NDEBUG
249| #define EXCEPT3_INITCHK( this )
250|#else
251| #define EXCEPT3_INITCHK( this ) \
252| if ( (this)->__initchk.var != ERRORS_INITCHK_MAGIC( &(this)->__initchk, \
253| (this)->__initchk.order, (this)->__initchk.key, \
254| (this)->__initchk.count ) ) { \
255| char msg[256]; \
256| sprintf( msg, "%s(%d) で c_try が呼ばれましたが Except3 が初期化されていません", \
257| __FILE__, __LINE__ ); \
258| Except3_error( Except3_Err_NoInit, msg ); \
259| }
260|#endif
261|
262|
263|/*************************************************************************
264|* 14. <<< [Except3_error] 例外処理システムの異常終了 >>>
265|**************************************************************************/
266|#define Except3_error( code, msg ) \
267| Except3_error_imp( code, msg, __FILE__, __LINE__ )
268|
269|
270|/*************************************************************************
271|* 15. <<< [Except3_getGlobl] システム領域のアドレスを返す >>>
272|**************************************************************************/
273|#ifdef USES_MULTASK
274| #define Except3_getGlobl() (&Except3_con[MulTask_Sys_getCurIndex()])
275|#else
276| #define Except3_getGlobl() (&Except3_con)
277|#endif
278|
279|
280|/*************************************************************************
281|* 16. <<< [c_try] try ブロック >>>
282|*【補足】
283|*・このブロックの内部で例外が発生したら、catch ブロック(c_catch)に
284|* ジャンプします。→「構造化例外処理の動作概要」
285|**************************************************************************/
286|#ifdef USES_MULTASK
287|
288| #define c_try \
289| EXCEPT3_INITCHK( &Except3_con[MulTask_Sys_getCurIndex()] ); \
290| if ( setjmp( Except3_con[MulTask_Sys_getCurIndex()]. \
291| tryInfo[Except3_con.nTry].longjmp_buf ) == 0 ) { \
292| Except3_try_imp( &Except3_con[MulTask_Sys_getCurIndex()], \
293| __FILE__, __LINE__ ); {
294|
295|#else
296|
297| #define c_try \
298| EXCEPT3_INITCHK( &Except3_con ); \
299| if ( setjmp( Except3_con.tryInfo[Except3_con.nTry].longjmp_buf ) == 0 ) { \
300| Except3_try_imp( &Except3_con, __FILE__, __LINE__ ); {
301|
302|#endif
303|
304|
305|
306|/*************************************************************************
307|* 17. <<< [c_catch, c_end_catch] catch ブロック >>>
308|*【補足】
309|*・try ブロック(c_try)の内部で例外が発生したら、このブロックに
310|* ジャンプします。→「構造化例外処理の動作概要」
311|*・msg には、throw したときに指定したアドレスが格納され、
312|* 指定した type 型(ポインタ型)になります。
313|*・catch ブロックの後には、c_end_catch か finally ブロックを記述してください。
314|*・catch ブロック内で break や return や goto を使わないでください。
315|*【補足】
316|*・type には、通常、Errors_Msg* 型を指定します。
317|**************************************************************************/
318|#ifdef USES_MULTASK
319|
320| #define c_catch( type, arg ) \
321| } } else if ( Except3_catch_imp( &Except3_con[MulTask_Sys_getCurIndex()] ) ) \
322| { type arg = (type)Except3_con.msg; \
323| {
324|
325| #define c_end_catch \
326| c_finally {} c_end_finally
327|
328|#else
329|
330| #define c_catch( type, arg ) \
331| } } else if ( Except3_catch_imp( &Except3_con ) ) \
332| { type arg = (type)Except3_con.msg; \
333| {
334|
335| #define c_end_catch \
336| c_finally {} c_end_finally
337|
338|#endif
339|
340|
341|
342|/*************************************************************************
343|* 18. <<< [c_finally, c_end_finally] finally ブロック >>>
344|*【補足】
345|*・catch ブロックの後に記述してください。
346|*・finally ブロックの終わりに end_finally を記述してください。
347|*・finally ブロックの内部で例外を発生させても構いませんが、
348|* エラーメッセージが上書きされる可能性があるので注意してください。
349|* return や break によって抜けたときの動作は未確認です。
350|*【例】
351|* c_finally {
352|* if ( obj != NULL ) Obj_finish( obj );
353|* if ( err ) error();
354|* } c_end_finally;
355|**************************************************************************/
356|#define c_finally \
357| } } \
358| {
359|
360|
361|#ifdef USES_MULTASK
362|
363| #define c_end_finally \
364| } \
365| Except3_end_finally_imp( &Except3_con[MulTask_Sys_getCurIndex()] );
366|
367|#else
368|
369| #define c_end_finally \
370| } \
371| Except3_end_finally_imp( &Except3_con );
372|
373|#endif
374|
375|
376|/*************************************************************************
377|* 19. <<< [c_throw, c_throw_again] 例外を投げる >>>
378|*【引数】
379|* ・void* msg; エラーメッセージ(catch へ)
380|*【補足】
381|*・msg には、通常、Errors_Msg* 型を指定します。
382|*・例外処理システムが msg を参照している期間は、catch ブロックで
383|* 正常に例外処理が終了するまでです。
384|**************************************************************************/
385|#ifdef USES_MULTASK
386|
387| #define c_throw( msg ) \
388| Except3_throw_imp( &Except3_con[MulTask_Sys_getCurIndex()], msg )
389|
390| #define c_throw_again() \
391| Except3_throw_imp( &Except3_con[MulTask_Sys_getCurIndex()], \
392| Except3_con[MulTask_Sys_getCurIndex()].msg )
393|
394|#else
395|
396| #define c_throw( msg ) \
397| Except3_throw_imp( &Except3_con, msg )
398|
399| #define c_throw_again() \
400| Except3_throw_imp( &Except3_con, Except3_con.msg )
401|
402|#endif
403|
404|
405|
406|/*************************************************************************
407|* 20. <<< [c_if_error, c_then, c_endif] 随時エラー確認スタイル >>>
408|*【引数】
409|* ・void* msg; エラーメッセージ(catch へ)
410|*【補足】
411|*・「随時エラー確認スタイルでの例外処理」の文章を参照。
412|**************************************************************************/
413|#define c_if_error c_try
414|#define c_then c_catch( Errors_Msg*, err )
415|#define c_endif c_end_catch
416|
417|
418|/*************************************************************************
419|* 21. <<< [Except3_startNoJumpArea] ロングジャンプしない領域を開始する >>>
420|**************************************************************************/
421|#ifdef USES_MULTASK
422|
423| #define Except3_startNoJumpArea() \
424| Except3_startNoJumpArea_imp( &Except3_con[MulTask_Sys_getCurIndex()] )
425|
426|#else
427|
428| #define Except3_startNoJumpArea() \
429| Except3_startNoJumpArea_imp( &Except3_con )
430|
431|#endif
432|
433|/*************************************************************************
434|* 22. <<< [Except3_endNoJumpArea] ロングジャンプしない領域を終了する >>>
435|**************************************************************************/
436|#ifdef USES_MULTASK
437|
438| #define Except3_endNoJumpArea() \
439| Except3_endNoJumpArea_imp( &Except3_con[MulTask_Sys_getCurIndex()] )
440|
441|#else
442|
443| #define Except3_endNoJumpArea() \
444| Except3_endNoJumpArea_imp( &Except3_con )
445|
446|#endif
447|
448|/*************************************************************************
449|* 23. <<< [Except3_isNoJumpArea] ロングジャンプしない領域かどうかを返す >>>
450|*【補足】
451|*・Except3_startNoJumpArea の内部または、c_try の外なら true を返します。
452|**************************************************************************/
453|#ifdef USES_MULTASK
454|
455| #define Except3_isNoJumpArea() \
456| Except3_isNoJumpArea_imp( &Except3_con[MulTask_Sys_getCurIndex()] )
457|
458|#else
459|
460| #define Except3_isNoJumpArea() \
461| Except3_isNoJumpArea_imp( &Except3_con )
462|
463|#endif
464|
465|/*************************************************************************
466|* 24. <<< [Except3_isError] 例外が発生しているかどうかを返す >>>
467|*【補足】
468|*・例外が複数段で発生すると、前のエラーメッセージが上書きされて消えてしまう
469|* ことがあるので、本マクロを使用して上書きしないようにしてください。
470|**************************************************************************/
471|#ifdef USES_MULTASK
472|
473| #define Except3_isError() \
474| Except3_isError_imp( &Except3_con[MulTask_Sys_getCurIndex()] )
475|
476|#else
477|
478| #define Except3_isError() \
479| Except3_isError_imp( &Except3_con )
480|
481|#endif
482|
483|
484|/*************************************************************************
485|* 25. <<< [Except3_isDblError] 例外が多重に発生したかどうかを返す >>>
486|*【補足】
487|*・例外が多重に発生するとは、複数の例外のメッセージが同じレベルの
488|* スタックを昇っていくことです。
489|*・例外が多重に発生した場合、正常に例外処理をすることができません。
490|* そうならないようにプログラムを工夫してください。
491|*・catch ブロックや finally ブロック の中の try ブロック内で例外が
492|* 発生しても、それに対応する catch ブロックで例外処理が完了すれば、
493|* 多重に例外が発生したことにはなりません。ただし、その場合、
494|* 例外が複数存在する瞬間があるのでエラーメッセージは一時的に
495|* スタックに格納する必要があります。
496|**************************************************************************/
497|#ifdef USES_MULTASK
498|
499| #define Except3_isDblError() \
500| Except3_con[MulTask_Sys_getCurIndex()].bDblError
501|
502|#else
503|
504| #define Except3_isDblError() \
505| Except3_con.bDblError
506|
507|#endif
508|
509|
510|/*************************************************************************
511|* 26. <<< [Except3_print] 例外処理システムの状態をデバッグ表示する >>>
512|**************************************************************************/
513|#ifdef USES_MULTASK
514|
515| #define Except3_print() \
516| Except3_print_imp( &Except3_con[MulTask_Sys_getCurIndex()], \
517| MulTask_Sys_getCurIndex() )
518|
519|#else
520|
521| #define Except3_print() \
522| Except3_print_imp( &Except3_con )
523|
524|#endif
525|
526|
527|/*--------------------------------------------------------------------*/
528|/* 27. <<<◆(Except3_MsgMng) エラーメッセージの管理 >>> */
529|/*--------------------------------------------------------------------*/
530|
531|
532|/*************************************************************************
533|* 28. <<< [Except3_MsgStack_push] メッセージをプッシュする >>>
534|*【引数】
535|* ・void* msg; プッシュするメッセージ
536|* ・void* 返り値; 次に使用するメッセージの記憶領域のアドレス
537|*【補足】
538|*・throw したときに呼び出されます。
539|*・通常、エラーメッセージを格納してから throw されるので、現在のエラー
540|* メッセージのコピーをあらかじめプッシュしておきます。
541|**************************************************************************/
542|
543|
544|/*************************************************************************
545|* 29. <<< [Except3_MsgStack_pop] メッセージをポップする >>>
546|*【引数】
547|* ・void* msg; 使用を終了する記憶領域のアドレス
548|* ・void* 返り値; 次に使用するメッセージの記憶領域のアドレス
549|*【補足】
550|*・catch ブロック(エラー処理)が終了したときに呼び出されます。
551|*・ポップしたエラーメッセージを現在のエラーメッセージに設定して、
552|* 返り値にします。
553|**************************************************************************/
554|
555|
556|#endif /* __EXCEPT3_H */
557|
558|