tagged release 0.6.4
[parrot.git] / src / pmc / exception_handler.pmc
blobb698d7578919f8e542a405fd775c2c48eedf2f74
1 /*
2 Copyright (C) 2001-2007, The Perl Foundation.
3 $Id$
5 =head1 NAME
7 src/pmc/exception_handler.pmc - Exception Handler PMC
9 =head1 DESCRIPTION
11 When an exception handler is called, the exception object is passed as
12 C<REG_PMC(interp, 5)>, the original contents of this register is in the
13 exception object's C<_P5> attribute.
15 =head2 Methods
17 =over 4
19 =cut
23 #include "parrot/parrot.h"
24 #include "parrot/oplib/ops.h"
26 static opcode_t *
27 pass_exception_args(PARROT_INTERP, const char *sig,
28         opcode_t *dest, parrot_context_t * old_ctx, ...)
30     va_list   ap;
31     opcode_t *next;
33     va_start(ap, old_ctx);
34     next = parrot_pass_args_fromc(interp, sig, dest, old_ctx, ap);
35     va_end(ap);
37     return next;
40 pmclass Exception_Handler extends Continuation need_ext {
44 =item C<void init()>
46 Initializes the exception handler.
48 =cut
52     VTABLE void init() {
53         PMC_struct_val(SELF) = new_continuation(INTERP, NULL);
54         PMC_pmc_val(SELF)    = PMCNULL;
56         /* an exception handler has no separate context; it's only a snapshot
57          * of an "earlier" context, which is contained in the interpreter's
58          * context - the stacks can only be deeper in the interpreter - so no
59          * mark of context is needed */
60         PObj_active_destroy_SET(SELF);
61     }
63     /*
64      * can't reuse Continuation's destroy yet -
65      * RT#46703 fix ref_count handling for exception_handlers first
66      *
67      * An Exception_Handler is kind of a limited Continuation
68      * (can only call 'up the stack').  Therefore we probably don't
69      * have to convert all RetContinuations to real Continuations
70      */
72     VTABLE void destroy() {
73         Parrot_cont * const cc = PMC_cont(SELF);
75         if (cc) {
76             mem_sys_free(cc);
77             PMC_struct_val(SELF) = NULL;
78         }
79     }
81     VTABLE PMC *clone() {
82         PMC * const result = SUPER();
83         PObj_custom_mark_CLEAR(result);
84         return result;
85     }
87     VTABLE opcode_t *invoke(void *ex) {
88         Parrot_cont        *cc        = PMC_cont(SELF);
89         PMC                *exception = (PMC *)ex;
90         opcode_t           *next      = NULL;
91         parrot_context_t   *ex_ctx;
92         opcode_t           *results;
94         /* COMPAT:  PMC *p5 = REG_PMC(interp, 5);*/
96         PARROT_ASSERT(cc->to_ctx == cc->from_ctx);
97         results = cc->current_results;
99         /* clear all results, so that continuation.invoke
100          * doesn't pass any args #' */
101         cc->to_ctx->current_results = cc->current_results = NULL;
102         ex_ctx                      = CONTEXT(interp);
103         next                        = SUPER(next);
105         if (results) {
106             STRING *message = VTABLE_get_string_keyed_int(INTERP,
107                     exception, 0);
108             PARROT_ASSERT(next == results);
109             next            = pass_exception_args(interp, "PS", next,
110                                                   ex_ctx, exception, message);
111         }
113         return next;
114     }
119 =back
121 =head1 HISTORY
123 Initial revision by leo 2003.07.10.
125 =cut
130  * Local variables:
131  *   c-file-style: "parrot"
132  * End:
133  * vim: expandtab shiftwidth=4:
134  */