zsh-users
 help / color / mirror / code / Atom feed
* Exception handling and "trap" vs. TRAPNAL()
@ 2005-09-29 20:07 DervishD
  2005-09-30 11:41 ` Peter Stephenson
  0 siblings, 1 reply; 3+ messages in thread
From: DervishD @ 2005-09-29 20:07 UTC (permalink / raw)
  To: Zsh Users

    Hi all :)

    Let's say we have this script, using exception handling:

--- cut here ---
#!/bin/zsh

emulate -L zsh

[[ "$1" = "trap" ]] && trap 'throw DEFAULT' ZERR
[[ "$1" = "TRAPZERR" ]] && function TRAPZERR() { throw DEFAULT ; }

function throw() {
  typeset -g EXCEPTION="$1"
  readonly THROW=0
  if (( TRY_BLOCK_ERROR == 0 )); then
    (( TRY_BLOCK_ERROR = 1 ))
  fi
  THROW= 2>/dev/null
}

function catch() {
    typeset -g CAUGHT
    if [[ $TRY_BLOCK_ERROR -gt 0 && $EXCEPTION = ${~1} ]]; then
        (( TRY_BLOCK_ERROR = 0 ))
        CAUGHT="$EXCEPTION"
        unset EXCEPTION
        return 0
    fi
    return 1
}

alias catch="noglob catch"


{
    print "Before throwing"
    # This should throw "DEFAULT" exception
    false
    throw EXCEPTION
    # This shouldn't be shown
    print "After throwing"
} always {
    catch * && print "Caught exception $CAUGHT"
    return 0
}

--- cut here ---

    Sorry for the size, but I want to make sure it is as
self-contained as possible. Well, I do the following:

    $ ./script trap
    Before throwing
    Caught exception EXCEPTION

    $ ./script TRAPZERR
    Before throwing
    Caught exception DEFAULT

    $ ./script
    Before throwing
    Caught exception EXCEPTION

    I'm puzzled. The "trap" trap is executed in the current
environment, so I assume it would throw "DEFAULT", as intended, as
soon as we hit the "false". It doesn't and I don't know why. OTOH,
the TRAPZERR function, which runs "throw" in its own environment,
works ok :??? WHY?

    AFAIK the "trap" builtin runs its arguments in the current
environment, so to say it's like an alias, like cutting and pasting
the code, but anyway that shouldn't be the problem, since "throw" is
using globals and so it affects running in any environment.

    The only thing that could be happening is that the ZERR trap
using "trap" is not setting "TRY_BLOCK_ERROR" to "1", or it sets the
variable but the variable gets reset upon exiting the trap :???

    Can anybody (and I really mean anybody, not Bart XD) explain this
to me? I would like to use something similar and I need to use "trap"
traps and not "TRAPNAL()" traps because I want to use LINENO and
probably a couple of variables which are local to the functions where
the ZERR trap can be raised.

    Thanks a lot in advance :)

    Raúl Núñez de Arenas Coronado

-- 
Linux Registered User 88736 | http://www.dervishd.net
http://www.pleyades.net & http://www.gotesdelluna.net
It's my PC and I'll cry if I want to...


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Exception handling and "trap" vs. TRAPNAL()
  2005-09-29 20:07 Exception handling and "trap" vs. TRAPNAL() DervishD
@ 2005-09-30 11:41 ` Peter Stephenson
  2005-10-01 15:37   ` DervishD
  0 siblings, 1 reply; 3+ messages in thread
From: Peter Stephenson @ 2005-09-30 11:41 UTC (permalink / raw)
  To: zsh-users

DervishD <zsh@dervishd.net> wrote:
> --- cut here ---
> #!/bin/zsh
> 
> emulate -L zsh
> 
> [[ "$1" = "trap" ]] && trap 'throw DEFAULT' ZERR
> [[ "$1" = "TRAPZERR" ]] && function TRAPZERR() { throw DEFAULT ; }
> 
> {
>     print "Before throwing"
>     # This should throw "DEFAULT" exception
>     false
>     throw EXCEPTION
>     # This shouldn't be shown
>     print "After throwing"
> } always {
>     catch * && print "Caught exception $CAUGHT"
>     return 0
> }
> 
> --- cut here ---
>     $ ./script trap
>     Before throwing
>     Caught exception EXCEPTION
>
>     I'm puzzled. The "trap" trap is executed in the current
> environment, so I assume it would throw "DEFAULT", as intended, as
> soon as we hit the "false". It doesn't and I don't know why. OTOH,
> the TRAPZERR function, which runs "throw" in its own environment,
> works ok :??? WHY?

Add some "print"s to the trap to see when it's triggering.  You may find it's
throwing additional exceptions at points you don't want it to which is
gumming things up.

Mixing traps with the exception functions in this ways is bound to be hairy
and I'd suggest you avoid doing it.

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070


This message has been scanned for viruses by BlackSpider MailControl - www.blackspider.com


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Exception handling and "trap" vs. TRAPNAL()
  2005-09-30 11:41 ` Peter Stephenson
@ 2005-10-01 15:37   ` DervishD
  0 siblings, 0 replies; 3+ messages in thread
From: DervishD @ 2005-10-01 15:37 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: zsh-users

    Hi Peter :)
 * Peter Stephenson <pws@csr.com> dixit:
> DervishD <zsh@dervishd.net> wrote:
> > --- cut here ---
> > #!/bin/zsh
> > 
> > emulate -L zsh
> > 
> > [[ "$1" = "trap" ]] && trap 'throw DEFAULT' ZERR
> > [[ "$1" = "TRAPZERR" ]] && function TRAPZERR() { throw DEFAULT ; }
> > 
> > {
> >     print "Before throwing"
> >     # This should throw "DEFAULT" exception
> >     false
> >     throw EXCEPTION
> >     # This shouldn't be shown
> >     print "After throwing"
> > } always {
> >     catch * && print "Caught exception $CAUGHT"
> >     return 0
> > }
> > 
> > --- cut here ---
> >     $ ./script trap
> >     Before throwing
> >     Caught exception EXCEPTION
> >
> >     I'm puzzled. The "trap" trap is executed in the current
> > environment, so I assume it would throw "DEFAULT", as intended, as
> > soon as we hit the "false". It doesn't and I don't know why. OTOH,
> > the TRAPZERR function, which runs "throw" in its own environment,
> > works ok :??? WHY?
> Add some "print"s to the trap to see when it's triggering.  You may find it's
> throwing additional exceptions at points you don't want it to which is
> gumming things up.

    The trap is triggering just in the "false" statement, and the
TRAPZERR works perfectly, it's the "trap" kind which is failing.
 
> Mixing traps with the exception functions in this ways is bound to be hairy
> and I'd suggest you avoid doing it.

    But the TRAPZERR works seamlessly :? In fact, I need to use
"trap" instead because I need to handle line numbers and the like,
otherwise I would stick to TRAPZERR. I can undertand that throwing
exceptions from within a trap can be hairy, but since I tested
TRAPZERR and it worked, I assumed that the system worked. I can avoid
using ZERR, of course, but that implies less clean code in some
scripts I have. I would have to substitute every command with
"command && throw $LINENO" or something similar (or worse, I would
have to think about a different name for the exceptions I need...) to
handle all errors in a common place. I don't even need exceptions for
this, but using exceptions and traps leads to much simpler, cleaner
and easier to maintain code.

    So: assuming that the trap is being triggered correctly (it is,
I've tested it), why "trap" is failing while "TRAPZERR" is working?
Can I do anything to make it work (except patching zsh)? Is there any
other way of throwing exceptions automagically when a command returns
a non-zero status or must I go for explicit code instead of making
the system implicit using ZERR?.

    Thanks a lot for your answer, Peter :) I was sure I was making
some obvious mistake O:)

    Raúl Núñez de Arenas Coronado

-- 
Linux Registered User 88736 | http://www.dervishd.net
http://www.pleyades.net & http://www.gotesdelluna.net
It's my PC and I'll cry if I want to...


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2005-10-01 15:37 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-09-29 20:07 Exception handling and "trap" vs. TRAPNAL() DervishD
2005-09-30 11:41 ` Peter Stephenson
2005-10-01 15:37   ` DervishD

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).