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

Last change on this file since 560 was 464, checked in by dai, 15 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.