先日公式BBSに例外処理のマクロがありまして
http://hsp.tv/play/pforum.php?mode=all&num=32385

それは、どう書く?orzを参考にしていまして
http://ja.doukaku.org/comment/8783/

著作権どうしよう?だなんて考えながらマクロ(?)を書きました
作成に二日かかったので
作成時間2〜4時間くらいで書いたままサイトにUPしてなかったんですけど
UPしてみます

公式BBSのは関数から例外が返って来ないんですけど
例外処理って普通の返り値と例外の二つ返す仕組みだとか
どこかで読んだ気がするんですけれど
なら返り値は引数に代入して
一つしかないけど返り値で例外を返せばいいじゃないか?という仕様です
例外の値は数値っぽいんですけど
しっかり設計しないといけなそうなので
例外の値は文字列にしました
文字列が等しければcatchという流れです
catchとfinallyは構造がまんまswitchではないか?
と思いまんまswitch使用して呼び方が違うだけです

FILE名:FILE_EX.hsp
#module EX
//	ユニークラベル操作
//	ユニークラベル取り出し。スタック維持
#define global __p_u_label %tEX_unique_label *%p
//	ユニークラベルをpop
#define global __o_u_label %tEX_unique_label *%o
goto *@f
//	変数をグローバル変数として扱いたいのでアクセサ付きとする
#deffunc __set_EX_val str p
__EX_val=p
return
#defcfunc __get_EX_val
return __EX_val
*@
//	アクセサ変数を空文字代入でRESET
#define global throw_RESET __set_EX_val ""
//	文字列をアクセサ変数に代入してユニークラベルにJUMP
#define global try_throw(%1) __set_EX_val %1:goto __p_u_label
//	ユニークラベルをスタックに積む
#define global try_begin %tEX_unique_label %i0
//	空命令
#define global try_end /**/

//	ユニークラベルを取り出して、そこがswitch文の開始
#define global b_catch __o_u_label:switch(__get_EX_val())
//	switch文終了
#define global b_catch_end swend

//	catchはcase文
#define global catch_begin(%1) case %1
#define global catch_end swbreak

//	finallyはdefault文
#define global finally_begin default
#define global finally_end swbreak

//	throwすると見せかけてreturnするだけ
#define global throw(%1) return %1
//	例外文字列が""か"nil"でなければ例外を投げる
#define global Does_try_throw(%1) __on_does_throw=%1:\
if (__on_does_throw!="")&(__on_does_throw!="nil"){try_throw __on_does_throw}
//	例外文字列が""か"nil"でなければ例外を返す
#define global Does_throw(%1) __on_does_throw=%1:\
if (__on_does_throw!="")&(__on_does_throw!="nil"){throw __on_does_throw}
#global

以下TESTコード
#include "FILE_EX.hsp"
goto *@f
#defcfunc throw_a01
throw "a01"
#defcfunc throw_a02
throw "a02"
#defcfunc throw_abc
throw "abc"
#defcfunc throw_null
throw ""
#defcfunc throw_nil
throw "nil"
*@
//	TEST例外処理の流れ
try_begin
try_throw "a01"
try_end
b_catch
catch_begin "a01"
mes "EX:This is a01"
catch_end
catch_begin "a02"
mes "EX:This is a02"
catch_end
finally_begin
mes "EX:This is fin"
finally_end
b_catch_end

try_begin
try_throw "a02"
try_end
b_catch
catch_begin "a01"
mes "EX:This is a01"
catch_end
catch_begin "a02"
mes "EX:This is a02"
catch_end
finally_begin
mes "EX:This is fin"
finally_end
b_catch_end

try_begin
try_throw "abc"
try_end
b_catch
catch_begin "a01"
mes "EX:This is a01"
catch_end
catch_begin "a02"
mes "EX:This is a02"
catch_end
finally_begin
mes "EX:This is fin"
finally_end
b_catch_end

//	TEST例外が返ってくる
try_begin
try_throw throw_a01()
try_end
b_catch
catch_begin "a01"
mes "EX:This is a01"
catch_end
catch_begin "a02"
mes "EX:This is a02"
catch_end
finally_begin
mes "EX:This is fin"
finally_end
b_catch_end

try_begin
try_throw throw_a02()
try_end
b_catch
catch_begin "a01"
mes "EX:This is a01"
catch_end
catch_begin "a02"
mes "EX:This is a02"
catch_end
finally_begin
mes "EX:This is fin"
finally_end
b_catch_end

try_begin
try_throw throw_abc()
try_end
b_catch
catch_begin "a01"
mes "EX:This is a01"
catch_end
catch_begin "a02"
mes "EX:This is a02"
catch_end
finally_begin
mes "EX:This is fin"
finally_end
b_catch_end

//	Does_try_throwのTEST
try_begin
Does_try_throw throw_a01()
try_end
b_catch
catch_begin "a01"
mes "EX:This is a01"
catch_end
catch_begin "a02"
mes "EX:This is a02"
catch_end
finally_begin
mes "EX:This is fin"
finally_end
b_catch_end

try_begin
Does_try_throw throw_null()
mes "null throw"
goto *@f
try_end
b_catch
catch_begin "a01"
mes "EX:This is a01"
catch_end
catch_begin "a02"
mes "EX:This is a02"
catch_end
finally_begin
mes "EX:This is fin"
finally_end
b_catch_end
*@

try_begin
Does_try_throw throw_nil()
mes "nil throw"
goto *@f
try_end
b_catch
catch_begin "a01"
mes "EX:This is a01"
catch_end
catch_begin "a02"
mes "EX:This is a02"
catch_end
finally_begin
mes "EX:This is fin"
finally_end
b_catch_end
*@

goto *@f
//	Does_throwのTEST用関数
#defcfunc throw_call_a01
Does_throw throw_a01()
return ""
//	Does_throwのTEST用関数
#defcfunc throw_call_null
Does_throw throw_null()
return ""
*@
//	Does_throwのTEST
try_begin
Does_try_throw throw_call_a01()
mes "null throw"
goto *@f
try_end
b_catch
catch_begin "a01"
mes "EX:This is a01"
catch_end
catch_begin "a02"
mes "EX:This is a02"
catch_end
finally_begin
mes "EX:This is fin"
finally_end
b_catch_end
*@
//	Does_throwのTEST
try_begin
Does_try_throw throw_call_null()
mes "null throw"
goto *@f
try_end
b_catch
catch_begin "a01"
mes "EX:This is a01"
catch_end
catch_begin "a02"
mes "EX:This is a02"
catch_end
finally_begin
mes "EX:This is fin"
finally_end
b_catch_end
*@