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

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

gcからのppTryLayersのスキャンに失敗してしまっていたため、List型に改修した。

File size: 5.3 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 MessageBox( NULL, ToTCStr(Ex"Catchされていない例外があります\r\n" + ex.ToString), NULL, MB_OK or MB_ICONEXCLAMATION )
132 Debug
133 Return
134 End If
135
136 ' スレッドへThrow処理を開始したことを通知
137 Imports System.Threading
138 Thread.CurrentThread().__Throw( ex )
139
140 '未解放なローカルオブジェクトを解放する
141 FreeLocalObjects()
142
143 Dim tryLayer = tryLayers[tryLayers.Count - 1]
144
145 Dim addressOfCatch = tryLayer.ResolveCatchesOverload( ex ) As LONG_PTR
146 If addressOfCatch = NULL Then
147 ' Catchが定義されていないときはFinallyへ誘導
148 addressOfCatch = tryLayer.addressOfFinally As LONG_PTR
149 End If
150
151
152 '--------------------------------------------------
153 ' スレッドのコンテキストを設定(Catchへ遷移する)
154 '--------------------------------------------------
155
156 Dim context As CONTEXT
157 context.ContextFlags = CONTEXT_CONTROL or CONTEXT_INTEGER
158 If GetThreadContext( GetCurrentThread(), context ) = 0 Then
159 ' TODO: エラー処理
160 debug
161 End If
162
163 '新しいip, sp, bpをセット
164#ifdef _WIN64
165 context.Rip = addressOfCatch As QWord
166 context.Rbp = tryLayer.basePtr
167 context.Rsp = tryLayer.stackPtr
168#else
169 context.Eip = addressOfCatch As DWord
170 context.Ebp = tryLayer.basePtr
171 context.Esp = tryLayer.stackPtr
172#endif
173
174#ifdef _DEBUG
175 Dim ThreadNum As Long
176 ThreadNum=_DebugSys_GetThread()
177 If ThreadNum <> -1 Then
178 _DebugSys_ProcNum[ThreadNum] = tryLayer.debugProcNum-1
179 End If
180#endif
181
182 If SetThreadContext( GetCurrentThread(), context ) = 0 Then
183 OutputDebugString(Ex"レジスタ情報の設定に失敗しました。\r\n")
184 Return
185 End If
186 End Sub
187
188 Sub _ThrowWithParam( ex As Object )
189 _Throw( ex )
190 End Sub
191
192 Sub _ThrowNoneParam()
193 _Throw( Nothing )
194 End Sub
195
196 Sub FinishFinally()
197 Dim tryLayer = tryLayers[tryLayers.Count - 1]
198 tryLayer.FinishFinally()
199 End Sub
200End Class
201
Note: See TracBrowser for help on using the repository browser.