C:\home\SVGCats_src\src\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|