source: trunk/ab5.0/ablib/src/system/exception.ab@ 506

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

Catchされていない例外はデバッグビューにもメッセージ出力するようにした。

File size: 5.4 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 Imports System.Threading
31 If Thread.CurrentThread().__IsThrowing() Then
32 Throw Thread.CurrentThread().__GetThrowintParamObject()
33 End If
34 End Sub
35
36 Function ResolveCatchesOverload( ex As Object ) As LONG_PTR
37 OutputDebugString("ResolveCatchesOverload: ")
38 OutputDebugString(ToTCStr(ex.ToString))
39 OutputDebugString(Ex"\r\n")
40 Dim defaultCatchCodePos = 0 As LONG_PTR
41 Dim pos = 0 As Long
42 While catchTable[pos]
43 ' パラメータのクラス名
44 Dim paramName = catchTable[pos] As *Char
45 pos ++
46
47 ' コード位置
48 Dim codePos = catchTable[pos] As LONG_PTR
49 pos ++
50
51 If paramName[0] = 0 Then
52 ' Default Catch
53 defaultCatchCodePos = codePos
54 End If
55
56 If Object.ReferenceEquals( ex, Nothing ) Then
57 ' パラメータなしのとき
58 If paramName[0] = 0 Then
59 ' マッチしたとき
60 Return codePos
61 End If
62 Else
63 If isCatchable(New String(paramName), ex.GetType()) Then
64' If lstrcmp( paramName, ex.GetType().FullName ) = 0 Then
65 ' マッチしたとき
66 Return codePos
67 End If
68 End If
69 Wend
70 Return defaultCatchCodePos
71 End Function
72Private
73 Function isCatchable(paramName As String, catchType As System.TypeInfo) As Boolean
74/* If Not String.IsNullOrEmpty(paramName) Then
75 Dim paramType = _System_TypeBase_Search(paramName)
76 isCatchable = ActiveBasic.Detail.IsBaseOf(catchType, paramType)
77 Else
78 isCatchable = False
79 End If
80/*/
81 isCatchable = False
82 While Not ActiveBasic.IsNothing(catchType)
83 Dim catchTypeName = catchType.FullName
84 If paramName = catchTypeName Then
85 isCatchable = True
86 Exit Function
87 End If
88 catchType = catchType.BaseType
89 Wend
90'*/
91 End Function
92End Class
93
94Class ExceptionService
95 tryLayers As System.Collections.Generic.List<TryLayer>
96
97 Sub FreeLocalObjects()
98 'TODO: 破棄されていないローカルオブジェクトを破棄
99 End Sub
100Public
101
102 Sub ExceptionService()
103 tryLayers = New System.Collections.Generic.List<TryLayer>
104 End Sub
105 Sub ~ExceptionService()
106 End Sub
107
108 'Try
109 Function _BeginTryScope( catchTable As *LONG_PTR, addressOfFinally As VoidPtr, basePtr As LONG_PTR, stackPtr As LONG_PTR ) As TryLayer
110 Dim tryLayer = New TryLayer( catchTable, addressOfFinally, basePtr, stackPtr )
111 tryLayers.Add( tryLayer )
112
113 Return tryLayer
114 End Function
115
116 Static Function BeginTryScope( catchTable As *LONG_PTR, addressOfFinally As VoidPtr, basePtr As LONG_PTR, stackPtr As LONG_PTR ) As TryLayer
117 Return _System_pobj_AllThreads->GetCurrentException()._BeginTryScope( catchTable, addressOfFinally, basePtr, stackPtr )
118 End Function
119
120 'End Try
121 Sub EndTryScope()
122 tryLayers.RemoveAt( tryLayers.Count - 1 )
123 End Sub
124
125 'Throw
126 Sub _Throw( ex As Object )
127 If tryLayers.Count <= 0 then
128 '例外処理スコープ制御が無効なとき
129
130 'TODO: 適切なエラー処理
131 System.Diagnostics.Debug.WriteLine( Ex"Catchされていない例外があります\r\n" + ex.ToString )
132 MessageBox( NULL, ToTCStr(Ex"Catchされていない例外があります\r\n" + ex.ToString), NULL, MB_OK or MB_ICONEXCLAMATION )
133 Debug
134 Return
135 End If
136
137 ' スレッドへThrow処理を開始したことを通知
138 Imports System.Threading
139 Thread.CurrentThread().__Throw( ex )
140
141 '未解放なローカルオブジェクトを解放する
142 FreeLocalObjects()
143
144 Dim tryLayer = tryLayers[tryLayers.Count - 1]
145
146 Dim addressOfCatch = tryLayer.ResolveCatchesOverload( ex ) As LONG_PTR
147 If addressOfCatch = NULL Then
148 ' Catchが定義されていないときはFinallyへ誘導
149 addressOfCatch = tryLayer.addressOfFinally As LONG_PTR
150 End If
151
152
153 '--------------------------------------------------
154 ' スレッドのコンテキストを設定(Catchへ遷移する)
155 '--------------------------------------------------
156
157 Dim context As CONTEXT
158 context.ContextFlags = CONTEXT_CONTROL or CONTEXT_INTEGER
159 If GetThreadContext( GetCurrentThread(), context ) = 0 Then
160 ' TODO: エラー処理
161 debug
162 End If
163
164 '新しいip, sp, bpをセット
165#ifdef _WIN64
166 context.Rip = addressOfCatch As QWord
167 context.Rbp = tryLayer.basePtr
168 context.Rsp = tryLayer.stackPtr
169#else
170 context.Eip = addressOfCatch As DWord
171 context.Ebp = tryLayer.basePtr
172 context.Esp = tryLayer.stackPtr
173#endif
174
175#ifdef _DEBUG
176 Dim ThreadNum As Long
177 ThreadNum=_DebugSys_GetThread()
178 If ThreadNum <> -1 Then
179 _DebugSys_ProcNum[ThreadNum] = tryLayer.debugProcNum-1
180 End If
181#endif
182
183 If SetThreadContext( GetCurrentThread(), context ) = 0 Then
184 OutputDebugString(Ex"レジスタ情報の設定に失敗しました。\r\n")
185 Return
186 End If
187 End Sub
188
189 Sub _ThrowWithParam( ex As Object )
190 _Throw( ex )
191 End Sub
192
193 Sub _ThrowNoneParam()
194 _Throw( Nothing )
195 End Sub
196
197 Sub FinishFinally()
198 Dim tryLayer = tryLayers[tryLayers.Count - 1]
199 tryLayer.FinishFinally()
200 End Sub
201End Class
202
Note: See TracBrowser for help on using the repository browser.