except3.h

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|