source: trunk/Include/system/exception.ab@ 374

Last change on this file since 374 was 374, checked in by dai, 16 years ago

例外処理機構実装中
・Catchのオーバーロードに対応
・Finallyに対応
・Tryスコープの入れ子に対応
(※注意 … 現時点ではThrow→Catch間でパラメータの引渡しができません)

File size: 4.8 KB
Line 
1'TODO: ローカルオブジェクト確保及び解放時にTryServiceに通知する必要がある。
2
3Class TryLayer
4Public
5 Const catchTable As *LONG_PTR
6 Const addressOfFinally As VoidPtr
7 Const basePtr As LONG_PTR
8 Const stackPtr As LONG_PTR
9
10 Const debugProcNum As DWord
11
12 Sub TryLayer( catchTable As *LONG_PTR, addressOfFinally As VoidPtr, basePtr As LONG_PTR, stackPtr As LONG_PTR )
13 This.catchTable = catchTable
14 This.addressOfFinally = addressOfFinally
15 This.basePtr = basePtr
16 This.stackPtr = stackPtr
17
18#ifdef _DEBUG
19 Dim ThreadNum As Long
20 ThreadNum=_DebugSys_GetThread()
21 If ThreadNum <> -1 Then
22 debugProcNum = _DebugSys_ProcNum[ThreadNum]
23 End If
24#endif
25 End Sub
26 Sub ~TryLayer()
27 End Sub
28
29 Sub FinishFinally()
30 If Thread.CurrentThread().__IsThrowing() Then
31 Throw Thread.CurrentThread().__GetThrowintParamObject()
32 End If
33 End Sub
34
35 Function ResolveCatchesOverload( ex As Object ) As LONG_PTR
36 Dim defaultCatchCodePos = 0 As LONG_PTR
37 Dim pos = 0 As Long
38 While catchTable[pos]
39 ' パラメータのクラス名
40 Dim paramName = catchTable[pos] As *Char
41 pos ++
42
43 ' コード位置
44 Dim codePos = catchTable[pos] As LONG_PTR
45 pos ++
46
47 If paramName[0] = 0 Then
48 ' Default Catch
49 defaultCatchCodePos = codePos
50 End If
51
52 If Object.ReferenceEquals( ex, Nothing ) Then
53 ' パラメータなしのとき
54 If paramName[0] = 0 Then
55 ' マッチしたとき
56 Return codePos
57 End If
58 Else
59 If lstrcmp( paramName, ex.GetType().FullName ) = 0 Then
60 ' マッチしたとき
61 Return codePos
62 End If
63 End If
64 Wend
65 Return defaultCatchCodePos
66 End Function
67End Class
68
69Class ExceptionService
70 ppTryLayers As **TryLayer
71 nTryLayers As Long
72
73 Sub FreeLocalObjects()
74 'TODO: 破棄されていないローカルオブジェクトを破棄
75 End Sub
76Public
77
78 Sub ExceptionService()
79 ppTryLayers = _System_malloc( 1 )
80 nTryLayers = 0
81 End Sub
82 Sub ~ExceptionService()
83 Dim i As Long
84 For i = 0 To ELM( nTryLayers )
85 Delete ppTryLayers[i]
86 Next
87 _System_free( ppTryLayers )
88 ppTryLayers = 0
89 End Sub
90
91 'Try
92 Function _BeginTryScope( catchTable As *LONG_PTR, addressOfFinally As VoidPtr, basePtr As LONG_PTR, stackPtr As LONG_PTR ) As TryLayer
93 ppTryLayers = _System_realloc( ppTryLayers, ( nTryLayers + 1 ) * SizeOf( *TryLayer ) )
94 ppTryLayers[nTryLayers] = New TryLayer( catchTable, addressOfFinally, basePtr, stackPtr )
95 nTryLayers++
96
97 Return ByVal ppTryLayers[nTryLayers-1]
98 End Function
99
100 Static Function BeginTryScope( catchTable As *LONG_PTR, addressOfFinally As VoidPtr, basePtr As LONG_PTR, stackPtr As LONG_PTR ) As TryLayer
101 Return _System_pobj_AllThreads->GetCurrentException()->_BeginTryScope( catchTable, addressOfFinally, basePtr, stackPtr )
102 End Function
103
104 'End Try
105 Sub EndTryScope()
106 nTryLayers--
107 Delete ppTryLayers[nTryLayers]
108 End Sub
109
110 'Throw
111 Sub _Throw( ex As Object )
112 If nTryLayers <= 0 then
113 '例外処理スコープ制御が無効なとき
114
115 'TODO: 適切なエラー処理
116 MessageBox( NULL, "例外", "", MB_OK or MB_ICONEXCLAMATION )
117
118 Return
119 End If
120
121 ' スレッドへThrow処理を開始したことを通知
122 Thread.CurrentThread().__Throw( ex )
123
124 '未解放なローカルオブジェクトを解放する
125 FreeLocalObjects()
126
127 Dim pTryLayer = ppTryLayers[nTryLayers - 1] As *TryLayer
128
129 Dim addressOfCatch = pTryLayer->ResolveCatchesOverload( ex ) As LONG_PTR
130 If addressOfCatch Then
131 ' スレッドへThrow処理が終了した(Catchされた)ことを通知
132 Thread.CurrentThread().__Catched()
133 Else
134 ' Catchが定義されていないときはFinallyへ誘導
135 addressOfCatch = pTryLayer->addressOfFinally As LONG_PTR
136 End If
137
138
139 '--------------------------------------------------
140 ' スレッドのコンテキストを設定(Catchへ遷移する)
141 '--------------------------------------------------
142
143 Dim context As CONTEXT
144 context.ContextFlags = CONTEXT_CONTROL or CONTEXT_INTEGER
145 If GetThreadContext( GetCurrentThread(), context ) = 0 Then
146 ' TODO: エラー処理
147 debug
148 End If
149
150 '新しいip, sp, bpをセット
151#ifdef _WIN64
152 context.Rip = addressOfCatch As QWord
153 context.Rbp = pTryLayer->basePtr
154 context.Rsp = pTryLayer->stackPtr
155#else
156 context.Eip = addressOfCatch As DWord
157 context.Ebp = pTryLayer->basePtr
158 context.Esp = pTryLayer->stackPtr
159#endif
160
161#ifdef _DEBUG
162 Dim ThreadNum As Long
163 ThreadNum=_DebugSys_GetThread()
164 If ThreadNum <> -1 Then
165 _DebugSys_ProcNum[ThreadNum] = pTryLayer->debugProcNum-1
166 End If
167#endif
168
169 If SetThreadContext( GetCurrentThread(), context ) = 0 Then
170 OutputDebugString(Ex"レジスタ情報の設定に失敗しました。\r\n")
171 Return
172 End If
173 End Sub
174
175 Sub _ThrowWithParam( ex As Object )
176 _Throw( ex )
177 End Sub
178
179 Sub _ThrowNoneParam()
180 _Throw( Nothing )
181 End Sub
182
183 Sub FinishFinally()
184 Dim pTryLayer = ppTryLayers[nTryLayers - 1] As *TryLayer
185 pTryLayer->FinishFinally()
186 End Sub
187End Class
188
Note: See TracBrowser for help on using the repository browser.