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

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

Throw→Catch間のパラメータ引渡しに対応。
グローバル領域でのTryスコープを可能にした。これで例外処理機構実装完了。
エディタの補間機能にTry/Catch/Finally/EndTryを追加。

File size: 4.7 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 = NULL Then
131 ' Catchが定義されていないときはFinallyへ誘導
132 addressOfCatch = pTryLayer->addressOfFinally As LONG_PTR
133 End If
134
135
136 '--------------------------------------------------
137 ' スレッドのコンテキストを設定(Catchへ遷移する)
138 '--------------------------------------------------
139
140 Dim context As CONTEXT
141 context.ContextFlags = CONTEXT_CONTROL or CONTEXT_INTEGER
142 If GetThreadContext( GetCurrentThread(), context ) = 0 Then
143 ' TODO: エラー処理
144 debug
145 End If
146
147 '新しいip, sp, bpをセット
148#ifdef _WIN64
149 context.Rip = addressOfCatch As QWord
150 context.Rbp = pTryLayer->basePtr
151 context.Rsp = pTryLayer->stackPtr
152#else
153 context.Eip = addressOfCatch As DWord
154 context.Ebp = pTryLayer->basePtr
155 context.Esp = pTryLayer->stackPtr
156#endif
157
158#ifdef _DEBUG
159 Dim ThreadNum As Long
160 ThreadNum=_DebugSys_GetThread()
161 If ThreadNum <> -1 Then
162 _DebugSys_ProcNum[ThreadNum] = pTryLayer->debugProcNum-1
163 End If
164#endif
165
166 If SetThreadContext( GetCurrentThread(), context ) = 0 Then
167 OutputDebugString(Ex"レジスタ情報の設定に失敗しました。\r\n")
168 Return
169 End If
170 End Sub
171
172 Sub _ThrowWithParam( ex As Object )
173 _Throw( ex )
174 End Sub
175
176 Sub _ThrowNoneParam()
177 _Throw( Nothing )
178 End Sub
179
180 Sub FinishFinally()
181 Dim pTryLayer = ppTryLayers[nTryLayers - 1] As *TryLayer
182 pTryLayer->FinishFinally()
183 End Sub
184End Class
185
Note: See TracBrowser for help on using the repository browser.