Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
tag: RELEASE_3_2_0
Fetching contributors…

Cannot retrieve contributors at this time

990 lines (724 sloc) 26.188 kb
/*
Copyright (C) 2001-2011, Parrot Foundation.
=head1 NAME
src/pmc/exception.pmc - Exception PMC
=head1 DESCRIPTION
This is the exception base class. An exception object has the following
attributes:
=over 4
=item C<message>
Textual representation of the exception.
=item C<severity>
The severity of the exception, (see F<include/parrot/exceptions.h>,
F<except_severity.pasm>).
=item C<type>
The type of the exception.
=item C<exit_code>
The exit code of the exception. (Added temporarily, to be removed.)
=item C<handled>
Whether the exception has been handled. Defaults to 0, 1 for handled, -1 for a
rethrown exception.
=item C<payload>
Additional data for the exception.
=back
When an exception handler is called, the exception object is passed as
as the first argument, the message as the second argument of the call.
These arguments can be retrieved with the C<get_results> opcode.
=cut
*/
#include "parrot/exceptions.h"
#include "pmc/pmc_sub.h"
typedef enum {
attr_id,
attr_birthtime,
attr_message,
attr_payload,
attr_resume,
attr_severity,
attr_type,
attr_exit_code,
attr_backtrace,
attr_handled,
attr_handler_iter,
attr_handler_ctx,
attr_thrower,
attr_bt_strings,
attr_NONE = -1
} AttrEnum;
/* HEADERIZER HFILE: none */
/* HEADERIZER BEGIN: static */
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
static AttrEnum getAttrEnum(PARROT_INTERP, ARGIN(const STRING *name))
__attribute__nonnull__(1)
__attribute__nonnull__(2);
#define ASSERT_ARGS_getAttrEnum __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(name))
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
/* HEADERIZER END: static */
pmclass Exception provides Exception auto_attrs {
ATTR INTVAL id; /* The task ID in the scheduler. */
ATTR FLOATVAL birthtime; /* The creation time stamp of the exception. */
ATTR STRING *message; /* The exception message. */
ATTR PMC *payload; /* The payload for the exception. */
ATTR PMC *resume; /* Continuation for resuming after handling the exception. */
ATTR INTVAL severity; /* The severity of the exception. */
ATTR INTVAL type; /* The type of the exception. */
ATTR INTVAL exit_code; /* The exit code of the exception. */
ATTR PMC *backtrace; /* The backtrace of an exception. */
ATTR INTVAL handled; /* Whether the exception has been handled. */
ATTR PMC *handler_iter; /* An iterator of handlers (for rethrow). */
ATTR PMC *handler_ctx; /* A stored context for handler iterator. */
ATTR PMC *thrower; /* The position we were at when thrown. */
ATTR PMC *bt_strings; /* A cache of old backtraces, for rethrows */
/*
=head2 Vtable Functions
=over 4
=item C<void init()>
Initializes the exception with default values.
=cut
*/
VTABLE void init() {
/* Use custom mark */
PObj_custom_mark_SET(SELF);
/* Set default values */
SET_ATTR_message(INTERP, SELF, STRINGNULL);
SET_ATTR_payload(INTERP, SELF, PMCNULL);
SET_ATTR_resume(INTERP, SELF, PMCNULL);
SET_ATTR_severity(INTERP, SELF, EXCEPT_error);
SET_ATTR_backtrace(INTERP, SELF, PMCNULL);
SET_ATTR_handler_iter(INTERP, SELF, PMCNULL);
SET_ATTR_handler_ctx(INTERP, SELF, PMCNULL);
SET_ATTR_thrower(INTERP, SELF, PMCNULL);
SET_ATTR_bt_strings(INTERP, SELF, PMCNULL);
}
/*
=item C<void init_int()>
Initializes the exception with default values and the specified type.
=cut
*/
VTABLE void init_int(INTVAL type) {
SELF.init();
SET_ATTR_type(INTERP, SELF, type);
}
/*
=item C<void init_pmc()>
Initializes the exception with supplied values.
=cut
*/
VTABLE void init_pmc(PMC *values) {
INTVAL severity_val = EXCEPT_error;
STRING *message_val = NULL;
const INTVAL ishash = VTABLE_isa(INTERP, values, CONST_STRING(INTERP, "Hash"));
STATICSELF.init();
if (ishash) {
STRING * const severity = CONST_STRING(INTERP, "severity");
STRING * const message = CONST_STRING(INTERP, "message");
severity_val = VTABLE_get_integer_keyed_str(INTERP, values, severity);
message_val = VTABLE_get_string_keyed_str(INTERP, values, message);
}
else
message_val = VTABLE_get_string(INTERP, values);
/* Set up the values for the exception object. */
SET_ATTR_severity(INTERP, SELF, severity_val);
if (! STRING_IS_NULL(message_val))
SET_ATTR_message(INTERP, SELF, message_val);
}
/*
=item C<PMC *clone()>
Create a copy of the Exception.
Copy only the user supplied values, not the throwing and handling
information.
=cut
*/
VTABLE PMC *clone() {
PMC * const dest = Parrot_pmc_new(INTERP, SELF->vtable->base_type);
INTVAL id;
STRING *message;
PMC *payload;
INTVAL severity;
INTVAL type;
INTVAL exit_code;
PMC *bt_strings;
GET_ATTR_id(INTERP, SELF, id);
SET_ATTR_id(INTERP, dest, id);
GET_ATTR_message(INTERP, SELF, message);
SET_ATTR_message(INTERP, dest, message);
GET_ATTR_severity(INTERP, SELF, severity);
SET_ATTR_severity(INTERP, dest, severity);
GET_ATTR_type(INTERP, SELF, type);
SET_ATTR_type(INTERP, dest, type);
GET_ATTR_exit_code(INTERP, SELF, exit_code);
SET_ATTR_exit_code(INTERP, dest, exit_code);
GET_ATTR_bt_strings(INTERP, SELF, bt_strings);
if (!PMC_IS_NULL(bt_strings)) {
bt_strings = VTABLE_clone(INTERP, bt_strings);
SET_ATTR_bt_strings(INTERP, SELF, bt_strings);
}
GET_ATTR_payload(INTERP, SELF, payload);
if (!PMC_IS_NULL(payload)) {
payload = VTABLE_clone(INTERP, payload);
SET_ATTR_payload(INTERP, dest, payload);
}
return dest;
}
/*
=item C<void visit(PMC *visit)>
=item C<void freeze(PMC *visit)>
=item C<void thaw(PMC *visit)>
Implement interfaces required for storage in PBC.
Store only user-supplied, persistable values; not ephemeral data such as
throwing and handling information.
=cut
*/
VTABLE void visit(PMC *visit) {
VISIT_PMC_ATTR(INTERP, visit, SELF, Exception, payload);
}
VTABLE void freeze(PMC *visit) {
INTVAL type, severity, exit_code;
STRING *message;
GET_ATTR_type(INTERP, SELF, type);
VTABLE_push_integer(INTERP, visit, type);
GET_ATTR_severity(INTERP, SELF, severity);
VTABLE_push_integer(INTERP, visit, severity);
GET_ATTR_exit_code(INTERP, SELF, exit_code);
VTABLE_push_integer(INTERP, visit, exit_code);
GET_ATTR_message(INTERP, SELF, message);
VTABLE_push_string(INTERP, visit, message);
}
VTABLE void thaw(PMC *visit) {
INTVAL type, severity, exit_code;
STRING *message;
type = VTABLE_shift_integer(INTERP, visit);
SET_ATTR_type(INTERP, SELF, type);
severity = VTABLE_shift_integer(INTERP, visit);
SET_ATTR_severity(INTERP, SELF, severity);
exit_code = VTABLE_shift_integer(INTERP, visit);
SET_ATTR_exit_code(INTERP, SELF, exit_code);
message = VTABLE_shift_string(INTERP, visit);
SET_ATTR_message(INTERP, SELF, message);
}
/*
=item C<void mark()>
Mark any active exception data as live.
=cut
*/
VTABLE void mark() {
Parrot_Exception_attributes * const core_struct = PARROT_EXCEPTION(SELF);
Parrot_gc_mark_STRING_alive(INTERP, core_struct->message);
Parrot_gc_mark_PMC_alive(INTERP, core_struct->payload);
Parrot_gc_mark_PMC_alive(INTERP, core_struct->resume);
Parrot_gc_mark_PMC_alive(INTERP, core_struct->backtrace);
Parrot_gc_mark_PMC_alive(INTERP, core_struct->handler_iter);
Parrot_gc_mark_PMC_alive(INTERP, core_struct->handler_ctx);
Parrot_gc_mark_PMC_alive(INTERP, core_struct->thrower);
Parrot_gc_mark_PMC_alive(INTERP, core_struct->bt_strings);
}
/*
=item C<INTVAL get_bool()>
Return true.
=cut
*/
VTABLE INTVAL get_bool() {
return 1;
}
/*
=item C<STRING *get_string()>
Return the exception message.
=cut
*/
VTABLE STRING *get_string() {
STRING *message;
GET_ATTR_message(INTERP, SELF, message);
if (STRING_IS_NULL(message))
message = CONST_STRING(INTERP, "");
return message;
}
/*
=item C<INTVAL get_integer()>
Returns the id of the exception.
=cut
*/
VTABLE INTVAL get_integer() {
const Parrot_Exception_attributes * const exception = PARROT_EXCEPTION(SELF);
return exception->id;
}
/*
=item C<STRING *get_string_keyed(PMC *key)>
Returns the Parrot string value for C<*key>. The only current recognized
C<key> is "message".
=cut
*/
VTABLE STRING *get_string_keyed(PMC *key) {
STRING * const name = VTABLE_get_string(INTERP, key);
STRING *message;
if (STRING_equal(INTERP, name, CONST_STRING(INTERP, "message"))) {
message = SELF.get_string();
}
else {
/* If unknown attribute name, throw an exception. */
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_ATTRIB_NOT_FOUND,
"No such string attribute '%S'", name);
}
return message;
}
/*
=item C<INTVAL get_integer_keyed_str(STRING *key)>
Returns the integer value for C<*key>.
=cut
*/
VTABLE INTVAL get_integer_keyed_str(STRING *key) {
INTVAL result = 0;
switch (getAttrEnum(INTERP, key)) {
case attr_type:
GET_ATTR_type(INTERP, SELF, result);
break;
case attr_severity:
GET_ATTR_severity(INTERP, SELF, result);
break;
case attr_exit_code:
GET_ATTR_exit_code(INTERP, SELF, result);
break;
case attr_handled:
GET_ATTR_handled(INTERP, SELF, result);
break;
default:
/* If unknown attribute name, throw an exception. */
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_ATTRIB_NOT_FOUND,
"No such integer attribute '%S'", key);
}
return result;
}
/*
=item C<INTVAL get_integer_keyed(PMC *key)>
Returns the integer value for C<*key>.
=cut
*/
VTABLE INTVAL get_integer_keyed(PMC *key) {
STRING * const name = VTABLE_get_string(INTERP, key);
return SELF.get_integer_keyed_str(name);
}
/*
=item C<PMC *get_pmc_keyed(PMC *key)>
Returns the PMC value for C<*key>.
=cut
*/
VTABLE PMC *get_pmc_keyed(PMC *key) {
STRING * const s = VTABLE_get_string(INTERP, key);
return SELF.get_attr_str(s);
}
/*
=item C<void set_string_native(STRING *value)>
Sets the C<message> of the Exception.
=cut
*/
VTABLE void set_string_native(STRING *value) {
SET_ATTR_message(INTERP, SELF, value);
}
/*
=item C<void set_integer_native(INTVAL *value)>
Sets the C<id> of the Exception.
=cut
*/
VTABLE void set_integer_native(INTVAL value) {
SET_ATTR_id(INTERP, SELF, value);
}
/*
=item C<void set_number_native(FLOATVAL value)>
Sets the birthtime of the exception.
=cut
*/
VTABLE void set_number_native(FLOATVAL value) {
SET_ATTR_birthtime(INTERP, SELF, value);
}
/*
=item C<void set_string_keyed(PMC *key, STRING *value)>
Sets the Parrot string value for C<*key>.
=cut
*/
VTABLE void set_string_keyed(PMC *key, STRING *value) {
STRING * const name = VTABLE_get_string(INTERP, key);
if (STRING_equal(INTERP, name, CONST_STRING(INTERP, "message"))) {
SELF.set_string_native(value);
}
else {
/* If unknown attribute name, throw an exception. */
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_ATTRIB_NOT_FOUND,
"No such string attribute '%S'", name);
}
}
/*
=item C<void set_integer_keyed_str(STRING *key, INTVAL value) >
Sets the integer value for C<*key>.
=cut
*/
VTABLE void set_integer_keyed_str(STRING *key, INTVAL value) {
switch (getAttrEnum(INTERP, key)) {
case attr_type:
SET_ATTR_type(INTERP, SELF, value);
break;
case attr_severity:
SET_ATTR_severity(INTERP, SELF, value);
break;
case attr_exit_code:
SET_ATTR_exit_code(INTERP, SELF, value);
break;
case attr_handled:
SET_ATTR_handled(INTERP, SELF, value);
break;
default:
/* If unknown attribute name, throw an exception. */
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_ATTRIB_NOT_FOUND,
"No such integer attribute '%S'", key);
}
}
/*
=item C<void set_integer_keyed(PMC *key, INTVAL value)>
Sets the integer value for C<*key>.
=cut
*/
VTABLE void set_integer_keyed(PMC *key, INTVAL value) {
STRING * const name = VTABLE_get_string(INTERP, key);
SELF.set_integer_keyed_str(name, value);
}
/*
=item C<void set_pmc_keyed(PMC *key, PMC *value)>
Sets the PMC value for C<*key>.
=cut
*/
VTABLE void set_pmc_keyed(PMC *key, PMC *value) {
STRING * const s = VTABLE_get_string(INTERP, key);
SELF.set_attr_str(s, value);
}
/*
=item C<void set_pointer(void *context)>
Store a context for the handler iterator.
=cut
*/
VTABLE void set_pointer(void *context) {
Parrot_Exception_attributes * const core_struct = PARROT_EXCEPTION(SELF);
core_struct->handler_ctx = (PMC*)context;
}
/*
=item C<void *get_pointer()>
Retrieve a context stored for the handler iterator.
=cut
*/
VTABLE void *get_pointer() {
const Parrot_Exception_attributes * const core_struct = PARROT_EXCEPTION(SELF);
return core_struct->handler_ctx;
}
/*
=item C<INTVAL is_equal(PMC *value)>
Compare the passed in Exception with C<SELF>. Returns true if C<SELF> and
C<value> are the same type, and have the same values for type, severity, and
exit_code.
=cut
*/
VTABLE INTVAL is_equal(PMC *value) {
STRING * const exception_str = CONST_STRING(INTERP, "Exception");
if (value->vtable->base_type == SELF->vtable->base_type
&& VTABLE_isa(INTERP, value, exception_str)) {
INTVAL self_compare, value_compare;
GET_ATTR_type(INTERP, SELF, self_compare);
GET_ATTR_type(INTERP, value, value_compare);
if (self_compare == value_compare) {
GET_ATTR_severity(INTERP, SELF, self_compare);
GET_ATTR_severity(INTERP, value, value_compare);
if (self_compare == value_compare) {
GET_ATTR_exit_code(INTERP, SELF, self_compare);
GET_ATTR_exit_code(INTERP, value, value_compare);
if (self_compare == value_compare)
return 1;
}
}
}
return 0;
}
/*
=item C<get_attr_str>
Retrieve an attribute value for the exception object.
=cut
*/
VTABLE PMC *get_attr_str(STRING *name) {
PMC *value = PMCNULL;
switch (getAttrEnum(INTERP, name)) {
case attr_type:
{
INTVAL type;
GET_ATTR_type(INTERP, SELF, type);
value = Parrot_pmc_new_init_int(INTERP, enum_class_Integer, type);
}
break;
case attr_severity:
{
INTVAL severity;
GET_ATTR_severity(INTERP, SELF, severity);
value = Parrot_pmc_new_init_int(INTERP, enum_class_Integer, severity);
}
break;
case attr_exit_code:
{
INTVAL exit_code;
GET_ATTR_exit_code(INTERP, SELF, exit_code);
value = Parrot_pmc_new_init_int(INTERP, enum_class_Integer, exit_code);
}
break;
case attr_handled:
{
INTVAL handled;
GET_ATTR_handled(INTERP, SELF, handled);
value = Parrot_pmc_new_init_int(INTERP, enum_class_Integer, handled);
}
break;
case attr_message:
{
STRING * const message = SELF.get_string();
value = Parrot_pmc_new(INTERP, enum_class_String);
VTABLE_set_string_native(INTERP, value, message);
}
break;
case attr_birthtime:
{
FLOATVAL birthtime;
GET_ATTR_birthtime(INTERP, SELF, birthtime);
value = Parrot_pmc_new(INTERP, enum_class_Float);
VTABLE_set_number_native(INTERP, value, birthtime);
}
break;
case attr_payload:
GET_ATTR_payload(INTERP, SELF, value);
break;
case attr_resume:
GET_ATTR_resume(INTERP, SELF, value);
break;
case attr_backtrace:
GET_ATTR_backtrace(INTERP, SELF, value);
break;
case attr_handler_iter:
GET_ATTR_handler_iter(INTERP, SELF, value);
break;
case attr_thrower:
GET_ATTR_thrower(INTERP, SELF, value);
break;
case attr_bt_strings:
GET_ATTR_bt_strings(INTERP, SELF, value);
break;
case attr_NONE:
/* If unknown attribute name, throw an exception. */
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_ATTRIB_NOT_FOUND,
"No such attribute '%S'", name);
default:
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
"Can't get attribute '%S'", name);
}
return value;
}
/*
=item C<set_attr_str>
Set an attribute value for the exception object.
=cut
*/
VTABLE void set_attr_str(STRING *name, PMC *value) {
switch (getAttrEnum(INTERP, name)) {
case attr_type:
{
const INTVAL type = VTABLE_get_integer(INTERP, value);
SET_ATTR_type(INTERP, SELF, type);
}
break;
case attr_severity:
{
const INTVAL severity = VTABLE_get_integer(INTERP, value);
SET_ATTR_severity(INTERP, SELF, severity);
}
break;
case attr_exit_code:
{
const INTVAL exit_code = VTABLE_get_integer(INTERP, value);
SET_ATTR_exit_code(INTERP, SELF, exit_code);
}
break;
case attr_handled:
{
const INTVAL handled = VTABLE_get_integer(INTERP, value);
SET_ATTR_handled(INTERP, SELF, handled);
}
break;
case attr_message:
{
STRING * const message = VTABLE_get_string(INTERP, value);
SELF.set_string_native(message);
}
break;
case attr_payload:
SET_ATTR_payload(INTERP, SELF, value);
break;
case attr_resume:
SET_ATTR_resume(INTERP, SELF, value);
break;
case attr_backtrace:
SET_ATTR_backtrace(INTERP, SELF, value);
break;
case attr_handler_iter:
SET_ATTR_handler_iter(INTERP, SELF, value);
break;
case attr_thrower:
SET_ATTR_thrower(INTERP, SELF, value);
break;
case attr_bt_strings:
SET_ATTR_bt_strings(INTERP, SELF, value);
break;
case attr_NONE:
/* If unknown attribute name, throw an exception. */
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_ATTRIB_NOT_FOUND,
"No such attribute '%S'", name);
default:
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
"Can't set attribute '%S'", name);
}
}
/*
=item C<PMC *share_ro()>
Set this PMC as shared.
=cut
*/
VTABLE PMC *share_ro() {
PMC *shared_self;
Parrot_Exception_attributes *shared_struct;
if (PObj_is_PMC_shared_TEST(SELF))
return SELF;
shared_self = pt_shared_fixup(INTERP, SELF);
shared_struct = PARROT_EXCEPTION(shared_self);
if (!PMC_IS_NULL(shared_struct->payload))
shared_struct->payload = pt_shared_fixup(INTERP, shared_struct->payload);
if (!PMC_IS_NULL(shared_struct->backtrace))
shared_struct->backtrace = pt_shared_fixup(INTERP, shared_struct->backtrace);
if (!PMC_IS_NULL(shared_struct->handler_iter))
shared_struct->handler_iter = pt_shared_fixup(INTERP, shared_struct->handler_iter);
return shared_self;
}
/*
=item C<PMC *annotations>
Gets any bytecode annotations in force at the point where the exception was
thrown. If the optional name of an annotation is specified, gets just that
annotation. If not, returns a Hash of all of them.
=cut
*/
METHOD annotations(STRING *name :optional, INTVAL have_name :opt_flag) {
PMC *resume;
PMC *result = PMCNULL;
/* Get resume continuation, to find location we failed at. */
GET_ATTR_resume(INTERP, SELF, resume);
if (!PMC_IS_NULL(resume)) {
const Parrot_Continuation_attributes * const cont = PARROT_CONTINUATION(resume);
if (cont->seg != NULL && cont->seg->annotations != NULL)
result = PackFile_Annotations_lookup(INTERP, cont->seg->annotations,
cont->address - cont->seg->base.data, name);
}
/* If we didn't have a key specified and we found no annotations to
* return, should return an empty hash. */
if (!have_name && PMC_IS_NULL(result))
result = Parrot_pmc_new(INTERP, enum_class_Hash);
RETURN(PMC *result);
}
/*
=item C<PMC *backtrace>
Gets a representation of the backtrace at the point that this exception was
thrown. Returns an array of hashes. Each array element represents a caller in
the backtrace, the most recent caller first. The hash has two keys: C<sub>,
which holds the PMC representing the sub, and C<annotations> which is a hash
of the annotations at the point where the exception was thrown for the current
sub, or for the point of the call a level deeper for the rest.
=cut
*/
METHOD backtrace() {
STRING * const meth_backtrace = CONST_STRING(INTERP, "backtrace");
PMC *result = PMCNULL;
PMC *resume;
/* Get starting context, then loop over them. */
GET_ATTR_resume(INTERP, SELF, resume);
if (!PMC_IS_NULL(resume)) {
/* We have a resume continuation, so we can get the address from that. */
const Parrot_Continuation_attributes * const cont = PARROT_CONTINUATION(resume);
Parrot_pcc_invoke_method_from_c_args(INTERP, cont->to_ctx, meth_backtrace,
"P->P", resume, &result);
}
else {
/* Hopefully we have a thrower set - our most epic fail fallback is
* to just assume the thrower is the current context. */
PMC *cur_ctx;
GET_ATTR_thrower(INTERP, SELF, cur_ctx);
if (PMC_IS_NULL(cur_ctx))
cur_ctx = CURRENT_CONTEXT(INTERP);
Parrot_pcc_invoke_method_from_c_args(INTERP, cur_ctx, meth_backtrace,
"->P", &result);
}
RETURN(PMC *result);
}
METHOD backtrace_strings() {
PMC * bt_strings = PMCNULL;
STRING * const bt = Parrot_dbg_get_exception_backtrace(INTERP, SELF);
GET_ATTR_bt_strings(INTERP, SELF, bt_strings);
if (PMC_IS_NULL(bt_strings))
bt_strings = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
VTABLE_unshift_string(INTERP, bt_strings, bt);
RETURN(PMC *bt_strings);
}
/*
=back
=cut
*/
}
/*
=head2 Auxliary functions
=over 4
=item C<static AttrEnum getAttrEnum(PARROT_INTERP, const STRING *name)>
Gets an enumerated value corresponding to the attribute with that name.
=cut
*/
static AttrEnum
getAttrEnum(PARROT_INTERP, ARGIN(const STRING *name))
{
ASSERT_ARGS(getAttrEnum)
AttrEnum r;
if (STRING_equal(interp, name, CONST_STRING(interp, "birthtime")))
r = attr_birthtime;
else if (STRING_equal(interp, name, CONST_STRING(interp, "message")))
r = attr_message;
else if (STRING_equal(interp, name, CONST_STRING(interp, "payload")))
r = attr_payload;
else if (STRING_equal(interp, name, CONST_STRING(interp, "resume")))
r = attr_resume;
else if (STRING_equal(interp, name, CONST_STRING(interp, "severity")))
r = attr_severity;
else if (STRING_equal(interp, name, CONST_STRING(interp, "type")))
r = attr_type;
else if (STRING_equal(interp, name, CONST_STRING(interp, "exit_code")))
r = attr_exit_code;
else if (STRING_equal(interp, name, CONST_STRING(interp, "backtrace")))
r = attr_backtrace;
else if (STRING_equal(interp, name, CONST_STRING(interp, "handled")))
r = attr_handled;
else if (STRING_equal(interp, name, CONST_STRING(interp, "handler_iter")))
r = attr_handler_iter;
else if (STRING_equal(interp, name, CONST_STRING(interp, "handler_ctx")))
r = attr_handler_ctx;
else if (STRING_equal(interp, name, CONST_STRING(interp, "thrower")))
r = attr_thrower;
else if (STRING_equal(interp, name, CONST_STRING(interp, "bt_strings")))
r = attr_bt_strings;
else
r = attr_NONE;
return r;
}
/*
=back
=cut
*/
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
*/
Jump to Line
Something went wrong with that request. Please try again.