EXCEPT.C

[目次 | 関数 | マクロ]

目次

関数一覧

マクロ一覧


   1|/***************************************************************************
   2|*  1. <<< 例外処理シュミレート (Except) >>> 
   3|*
   4|*・C 言語で例外処理をサポートします。
   5|*・C++ の例外処理と互換性はありませんが、それに近い文法を採用しています。
   6|*・次の2種類の例外型を実装しています。
   7|*   ・Except_Base 型 例外 [Except_...]
   8|*   ・Except_Std 型 例外 [Except_..., Except_Std_...]
   9|*
  10|*--------------------------------------------------------------------------
  11|*
  12|*  2. <<<【解説】例外処理をする >>>
  13|*
  14|* 例外処理は、おおよそ次のような構文をとります。
  15|*
  16|*    void  foo()
  17|*    {
  18|*      try {                             // try ブロック開始
  19|*        exceptable_func();  trys;       // try ブロック内のチェッカー
  20|*        if ( err )
  21|*          throw_trys( Except_s( "msg" ) );  // try ブロック内の throw
  22|*        normality_func();
  23|*      }
  24|*      catch ( msg ) {                   // catch ブロック開始
  25|*        if ( strcmp( ((Except_Std*)msg)->arg_str, "EOF" ) != 0 )
  26|*          return;
  27|*        Except_print( msg );
  28|*      } catch_end;
  29|*    }
  30|*
  31|*・try に続く中カッコで囲まれた部分(try ブロック)の中の関数の内部から
  32|*  投げられた例外(異常)を catch ブロックで受け取ります。上の場合、例外が
  33|*  投げられる可能性のある関数 exceptable_func() の内部から例外が投げられ
  34|*  ると、次に実行されるはずの if 文に続かずに直接 catch ブロックの中へ
  35|*  ジャンプします。
  36|*・投げられた例外は catch ブロックの msg に渡されます。
  37|*・例外が投げられる可能性のある関数は、必ず try ブロックの中に入れ、関数の
  38|*  直後に trys; を置きます。
  39|*・catch ブロックの終わりには、catch_end; を必ず置きます。
  40|*・try ブロックの中から例外を投げる場合は、throw_trys 文を用います。投げる
  41|*  例外を引数に渡します。
  42|*・try ブロックと catch ブロックのペアは、 1関数あたり1ペアしか使うことが
  43|*  できません。
  44|*
  45|*・例外処理を、コール元の関数に委譲する場合、
  46|*    void  foo()
  47|*    {
  48|*      exceptable_func();  throws;
  49|*    }
  50|*
  51|*  または
  52|*    int  foo()
  53|*    {
  54|*      exceptable_func();  throws_r(2);
  55|*    }
  56|*
  57|*  のようにします。例外が投げられる可能性のある関数の直後に、 throws または
  58|*  throws_r を置きます。throws throws_r は、返り値を指定するかどうかの
  59|*  違いだけです。
  60|*
  61|*・C++ の例外処理は、自動的にオブジェクトを delete しますが、この例外処理
  62|*  では、delete しないので、自動的にメモリの開放をしたり、ファイルを閉じたり
  63|*  することはありません。(その対処法は未定です。)
  64|*
  65|*--------------------------------------------------------------------------
  66|*
  67|*  3. <<<【解説】例外を投げる >>>
  68|*
  69|*・if 文などで、エラーを判定たら例外を投げます。構文は次の通りです。
  70|*     void  foo()
  71|*     {
  72|*       if ( error )  throw( Except_s( "msg" ) );
  73|*     }
  74|*
  75|*  または
  76|*     int  foo()
  77|*     {
  78|*       if ( error )  throw_r( Except_s( "msg" ), 2 );
  79|*     }
  80|*
  81|*・throw または throw_r 文で例外を投げます。上の場合、Except_s 関数の返り値
  82|*  である Except 型の例外(例外オブジェクト)を投げています。throw throw_r
  83|*  は、返り値を指定するかどうかの違いだけです。
  84|*・このような例外を投げる可能性のある関数は、「〜型の例外を投げる可能性がある
  85|*  」ことをドキュメントに明示しておくことを薦めます。
  86|*・try ブロックの中から例外を投げる場合は、throw_trys 文を用います。投げる
  87|*  例外を引数に渡します。
  88|*・catch ブロックの中から例外を投げることも出来ます。この場合、コール元の
  89|*  関数に例外が投げられます。
  90|*
  91|*・C++ の例外処理は、自動的にオブジェクトを delete しますが、この例外処理では、
  92|*  delete しないので、自動的にメモリの開放をしたり、ファイルを閉じたりすること
  93|*  はありません。一度 catch して開放してから再び throw します。
  94|*
  95|*--------------------------------------------------------------------------
  96|*
  97|*  4. <<< Except_Std クラス(Except 関数)>>>
  98|*
  99|*・一般的な例外オブジェクトです。
 100|*
 101|*     if ( error )  throw( Except() );
 102|*  のように Except 型例外を(生成し)投げて、
 103|*     catch ( msg ) {
 104|*        Except_print( msg );
 105|*     } catch_end;
 106|*  のように、一般的なエラー情報を表示します。
 107|*
 108|*・Except 型例外を生成する関数は次のものがあります。
 109|*     void* Except();
 110|*     void* Except_i( int hint );
 111|*     void* Excpet_s( char* hint );
 112|*  hint は、エラー情報のヒントで、Except_print 関数により表示されます。
 113|*
 114|*・例外オブジェクトは、Except_Base 型から派生させる必要があります。
 115|*  Except_Std 型も、Except_Base 型から派生しています。
 116|*・新しくクラス(型)を作ったら、 Except_Id 型に新しい要素を追加します。
 117|****************************************************************************/
 118|
 119|#include <stdio.h>
 120|#include <all.h>
 121|
 122|#ifdef _STDLIB
 123|  #define  Except_outPrintf    /* printf 表示 */
 124|#else
 125|  #define  Except_outWatch     /* watch 表示 */
 126|  #ifndef USES_WATCH
 127|  #error
 128|  #endif
 129|#endif
 130|
 131|
 132|/**************************************************************************
 133|*  5. <<< Except_Base 型 例外 [Except] >>>
 134|***************************************************************************/
 135|
 136|void*  Except_msg = NULL;  /* 例外オブジェクト用・スタック */
 137|char*  Except_file;  /* ファイル名 */
 138|int    Except_line;  /* 行番号 */
 139|
 140|
 141|/**************************************************************************
 142|*  6. <<< ファイル名と行番号を設定する [Except_setFileLine()] >>>
 143|***************************************************************************/
 144|void  Except_setFileLine( char* file, int line )
 145|{
 146|  Except_file = file;
 147|  Except_line = line;
 148|}
 149|
 150|
 151|/**************************************************************************
 152|*  7. <<< デフォルトの例外表示 [Except_print()] >>>
 153|***************************************************************************/
 154|void  Except_print( void* m )
 155|{
 156|  #ifdef  Except_outWatch
 157|    switch ( ((Except_Base*)m)->type ) {
 158|      case Except_idStd:
 159|        Except_Std_print( m );
 160|        break;
 161|      default:
 162|        watch( 0xECEF, __LINE__ );
 163|        break;
 164|    }
 165|  #endif /* Except_outWatch */
 166|  #ifdef  Except_outPrintf
 167|    printf("\n");
 168|    switch ( ((Except_Base*)m)->type ) {
 169|      case Except_idStd:
 170|        Except_Std_print( m );
 171|        break;
 172|      default:
 173|        printf( "Unknown Error in %s (%d) : %d\n",
 174|                Except_file, Except_line );
 175|        break;
 176|    }
 177|  #endif  /* Except_outPrintf */
 178|}
 179|
 180|
 181|/**************************************************************************
 182|*  8. <<< Except_Std 型 例外 [Except_Std] >>>
 183|***************************************************************************/
 184|
 185|Except_Std  Except_std = { Except_idStd, "Error", 0, NULL, 0 };
 186|
 187|
 188|/**************************************************************************
 189|*  9. <<< Except_Std 型 例外を発生させる [Except(), Except_s(), Except_i()] >>>
 190|***************************************************************************/
 191|void*  Except()
 192|{
 193|  Except_std.arg_type = 0;
 194|  return  &Except_std;
 195|}
 196|
 197|void*  Except_s( char* msg )
 198|{
 199|  Except_std.arg_type = 1;
 200|  Except_std.arg_str = msg;
 201|  return  &Except_std;
 202|}
 203|
 204|void*  Except_i( int msg )
 205|{
 206|  Except_std.arg_type = 2;
 207|  Except_std.arg_num = msg;
 208|  return  &Except_std;
 209|}
 210|
 211|
 212|/**************************************************************************
 213|*  10. <<< デバッグ表示 [Except_Std_print()] >>>
 214|*【補足】
 215|*・SDV デバッガでは、次のように出力されます。
 216|*   -dw w
 217|*   ECE0 0000004C ECE1 00004354  // ID, 型の名前
 218|*   ECE2 00004374 ECE3 0000006E  // 例外が発生したファイル、行
 219|*   ECE4 00004370                // メッセージ
 220|***************************************************************************/
 221|void  Except_Std_print( void* m )
 222|{
 223|  #ifdef Except_outWatch
 224|    watch( 0xECE0, __LINE__ );
 225|    watch( 0xECE1, (int)((Except_Std*)m)->str );
 226|    watch( 0xECE2, (int)Except_file );
 227|    watch( 0xECE3, Except_line );
 228|    switch( ((Except_Std*)m)->arg_type ) {
 229|      case 0:
 230|        break;
 231|      case 1:
 232|        watch( 0xECE4, (int)((Except_Std*)m)->arg_str );
 233|        break;
 234|      case 2:
 235|        watch( 0xECE4, ((Except_Std*)m)->arg_num );
 236|        break;
 237|    }
 238|  #endif  /* Except_outWatch */
 239|  #ifdef Except_outPrintf
 240|    printf( "%s in %s (%d)", ((Except_Std*)m)->str,
 241|                                       Except_file, Except_line );
 242|    switch( ((Except_Std*)m)->arg_type ) {
 243|      case 0:
 244|        printf( "\n" );
 245|        break;
 246|      case 1:
 247|        printf( " : %s\n", ((Except_Std*)m)->arg_str );
 248|        break;
 249|      case 2:
 250|        printf( " : %d\n", ((Except_Std*)m)->arg_num );
 251|        break;
 252|    }
 253|  #endif /* Except_outPrintf */
 254|}
 255| 
 256|