EXCEPT2.H

[目次 | 型・クラス・構造体 | マクロ]

目次

型・クラス・構造体一覧

マクロ一覧


   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 = &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|*  リリース版では、正式な例外処理構文(trycatch)を用いてください。
 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|*  リリース版では、正式な例外処理構文(trycatch)を用いてください。
 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|