注册 登录
Office中国论坛/Access中国论坛 返回首页

ganlinlao的个人空间 http://www.office-cn.net/?230471 [收藏] [复制] [分享] [RSS]

日志

不太好懂的try catch finally?

热度 1已有 2347 次阅读2016-10-13 10:44 |个人分类:FreeBasic| FreeBasic的try, catch, finally机制

众所周知,Freebasic和VBA一样也是使用On errror方式进行错误处理的,没有在语法上实现try catch finally的错误处理机制。那么如何自己实现Try catch finally呢,使用下面这个exceptions.bi的宏文件。
源代码如下:
#Ifndef EXCEPTION_RECORD
    #Error Please include windows.bi first!
#EndIf
#Ifndef __FB_WIN32__
    #Error Operating system not supported!
#EndIf

#Macro __trycheck(_name_)
    #Ifndef __eh_##_name_##_try_set
        #Error Undefined Try block name: _name_
    #EndIf
#EndMacro

#Macro Try(_name_)
    #Ifdef __eh_##_name_##_try_set2
        #Error Duplicated definition: _name_
    #EndIf
    #Define __eh_##_name_##_try_set
    #Define __eh_##_name_##_try_set2
    Scope
        Dim As Byte __eh_##_name_##_doret = 0
        Dim As Any Ptr __eh_##_name_##_ehesp = 0
        Dim As Byte __eh_##_name_##_ehandled = 0
        Dim As Byte __eh_##_name_##_wasincatch = 0
        Dim As EXCEPTION_RECORD Ptr __eh_##_name_##_erec = 0
        Dim As Byte __eh_##_name_##_erecarr(SizeOf(EXCEPTION_RECORD))
        Dim As Byte __eh_##_name_##_econarr(SizeOf(CONTEXT))
        Asm
            __eh_##_name_##_try:
            pushad
            mov esi, offset __eh_##_name_##_except
            push esi
            push dword ptr fs:[0]
            mov dword ptr fs:[0], esp       
        End Asm
        Scope
#EndMacro

#Macro __catch_codestart(_name_)
        End Scope
        #Define __eh_##_name_##_except_set
        Asm
            jmp __eh_##_name_##_finally_continue
            __eh_##_name_##_except:
            mov eax, [esp + 4]
            mov eax, [eax + 4]
            cmp eax, 2
            jne __eh_##_name_##_nounwind
            mov byte ptr [__eh_##_name_##_doret], 1
            call __eh_##_name_##_finally
            mov eax, 1
            ret
            __eh_##_name_##_nounwind:
            mov eax, esp
            mov esp, [esp + 8]
            pop dword ptr fs:[0]
            mov [esp], eax
            add esp, 4
            popad
            mov eax, [esp - 36]
            mov [__eh_##_name_##_ehesp], eax
            mov edx, eax         
        End Asm
        Scope
            Dim As EXCEPTION_RECORD Ptr ERecord
            Dim As CONTEXT Ptr EContext
            #Define ECode (ERecord->ExceptionCode)
            #Define EAddress (ERecord->ExceptionAddress)
            #Define ENumParams (ERecord->NumberParameters)
            #Define EParamsPtr CPtr(Integer Ptr, (@ERecord->ExceptionInformation(0)))
            Asm
                push edx
                mov edx, [edx + 8]
                mov [EContext], edx
                pop edx
                mov edx, [edx + 4]
                mov [ERecord], edx
            End Asm
            #Define __ersize (SizeOf(EXCEPTION_RECORD) + ERecord->NumberParameters * 4 - 4)
            #Define __erarrsize (UBound(__eh_##_name_##_erecarr) + 1)
            CopyMemory(Cast(Any Ptr, @__eh_##_name_##_erecarr(0)), Cast(Any Ptr, ERecord), IIf(__ersize <= __erarrsize, __ersize, __erarrsize))
            #Undef __erarrsize
            #Undef __ersize
            ERecord = Cast(EXCEPTION_RECORD Ptr, @__eh_##_name_##_erecarr(0))
            __eh_##_name_##_erec = ERecord
            CopyMemory(Cast(Any Ptr, @__eh_##_name_##_econarr(0)), Cast(Any Ptr, EContext), UBound(__eh_##_name_##_econarr) + 1)
            EContext = Cast(CONTEXT Ptr, @__eh_##_name_##_econarr(0))
            Select Case ECode           
#EndMacro

#Define EParams(_i_) IIf(EParamsPtr <> 0 AndAlso _i_ < ENumParams, (EParamsPtr)[_i_], 0)

#Macro __catch_next(_name_, _ecode_)
                #Define __ ,
                Case _ecode_
                #Undef __
                    Asm mov byte ptr [__eh_##_name_##_ehandled], 1
                    Asm mov byte ptr [__eh_##_name_##_wasincatch], 1
#EndMacro

#Macro Catch(_name_, _ecode_)
    __trycheck(_name_)
    #Ifdef __eh_##_name_##_finally_set
        #Error Using Catch after Finally not allowed!
    #EndIf
    #Ifndef __eh_##_name_##_except_set
        __catch_codestart(_name_)
    #EndIf
    __catch_next(_name_, _ecode_)
#EndMacro

#Macro Finally(_name_)
        #Ifdef __eh_##_name_##_finally_set
            #Error Multiple Finally statements not allowed!
        #EndIf
        __trycheck(_name_)
        #Ifndef __eh_##_name_##_except_set
            Catch(_name_, 0)
                __eh_##_name_##_ehandled = 0
        #EndIf
            End Select
        End Scope
        #Define __eh_##_name_##_finally_set
        Asm
            mov byte ptr [__eh_##_name_##_doret], 0
            __eh_##_name_##_finally:
        End Asm
        Scope
            Select Case 0
                Case 0
#EndMacro

#Macro Leave(_name_)
        __trycheck(_name_)
        Asm
            mov byte ptr [__eh_##_name_##_doret], 1
            call __eh_##_name_##_finally
        End Asm
#EndMacro

#Macro EndTry(_name_)
            __trycheck(_name_)
            #Ifndef __eh_##_name_##_except_set
                Catch(_name_, 0)
                    __eh_##_name_##_ehandled = 0
            #EndIf
            #Ifndef __eh_##_name_##_finally_set
                Finally(_name_)
            #EndIf
            End Select
        End Scope
        Asm
            cmp byte ptr [__eh_##_name_##_doret], 0
            je __eh_##_name_##_noret
            ret
            __eh_##_name_##_noret:
            cmp byte ptr [__eh_##_name_##_ehandled], 0
            jne __eh_##_name_##_continue
            mov esp, [__eh_##_name_##_ehesp]
        End Asm
        RaiseException(__eh_##_name_##_erec->ExceptionCode, __eh_##_name_##_erec->ExceptionFlags, __eh_##_name_##_erec->NumberParameters, @__eh_##_name_##_erec->ExceptionInformation(0))
        Asm
            int3
            __eh_##_name_##_finally_continue:
            mov byte ptr [__eh_##_name_##_doret], 1
            call __eh_##_name_##_finally
            pop dword ptr fs:[0]
            add esp, 36
            jmp __eh_##_name_##_end_try
            __eh_##_name_##_continue:
            cmp byte ptr [__eh_##_name_##_wasincatch], 1
            je __eh_##_name_##_end_try
            pop dword ptr fs:[0]
            add esp, 36
            __eh_##_name_##_end_try:
        End Asm
    End Scope
    #Undef __eh_##_name_##_try_set
#EndMacro

#Macro ExitTry(_name_)
    __trycheck(_name_)
    Leave(_name_)
    Asm jmp __eh_##_name_##_end_try
#EndMacro

#Macro RaiseParam(_ecode_, _nump_, _params_)
    Scope
        #Define __ ,
        Dim __params(_nump_ - 1) As Integer = {_params_}
        #Undef __
        RaiseException(_ecode_, 0, _nump_, @__params(0))
    End Scope
#EndMacro

#Macro Raise(_ecode_)
    RaiseException(_ecode_, 0, 0, 0)
#EndMacro


这个其实不好理解。有时间再继续深入了解一下。

发表评论 评论 (1 个评论)

回复 tmtony 2016-11-10 21:01
我的天啦。看晕了

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

QQ|站长邮箱|小黑屋|手机版|Office中国/Access中国 ( 粤ICP备10043721号-1 )  

GMT+8, 2024-3-29 04:17 , Processed in 0.073982 second(s), 18 queries .

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

返回顶部