Skip to content
Find file
Fetching contributors…
Cannot retrieve contributors at this time
1081 lines (759 sloc) 24.5 KB
/*
Copyright (C) 2001-2009, Parrot Foundation.
$Id$
=head1 NAME
src/pmc/unmanagedstruct.pmc - C struct with unmanaged memory
=head1 DESCRIPTION
PMC class to hold C C<struct>s that Parrot's not responsible for
disposing of.
Buffer can be accessed using keyed assignments to PMC. Out of
bounds access will very likely segfault.
=head2 Functions
=over 4
=cut
*/
#include "parrot/compiler.h"
static INTVAL key_2_idx(PARROT_INTERP, PMC *pmc, PMC *key);
static size_t calc_offsets(PARROT_INTERP, PMC*, PMC *init, size_t toff);
/*
=item C<static char *
char_offset_int(PARROT_INTERP, PMC *pmc, INTVAL ix, int *type)>
Returns the pointer for the element at index C<ix>, and sets the element
type in C<*type>.
=cut
*/
static char *
char_offset_int(PARROT_INTERP, PMC *pmc, INTVAL ix, int *type)
{
size_t offs, n;
ix *= 3;
if (!PARROT_UNMANAGEDSTRUCT(pmc)->init)
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNEXPECTED_NULL,
"Missing struct initializer");
n = (size_t)VTABLE_elements(interp, PARROT_UNMANAGEDSTRUCT(pmc)->init);
if ((size_t)ix >= n)
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNEXPECTED_NULL,
"Non existent elements in struct ix = %d n=%d", (int)ix, (int)n);
/* use structure init */
*type = (int) VTABLE_get_integer_keyed_int(interp,
PARROT_UNMANAGEDSTRUCT(pmc)->init, ix);
offs = (size_t) VTABLE_get_integer_keyed_int(interp,
PARROT_UNMANAGEDSTRUCT(pmc)->init, ix + 2);
return ((char *)VTABLE_get_pointer(interp, pmc)) + offs;
}
/*
=item C<static INTVAL
key_2_idx(PARROT_INTERP, PMC *pmc, PMC *key)>
Returns the index for the element associated with key C<*key>. Raises an
exception if the key doesn't exist.
=cut
*/
static INTVAL
key_2_idx(PARROT_INTERP, PMC *pmc, PMC *key)
{
int ix = 0;
if (!PARROT_UNMANAGEDSTRUCT(pmc)->init)
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_UNEXPECTED_NULL,
"Missing struct initializer");
if (PObj_get_FLAGS(key) & KEY_string_FLAG) {
PMC * const types = PARROT_UNMANAGEDSTRUCT(pmc)->init;
if (types->vtable->base_type == enum_class_OrderedHash) {
Hash * const hash = (Hash *)VTABLE_get_pointer(interp, types);
HashBucket * const b = parrot_hash_get_bucket(interp, hash,
VTABLE_get_string(interp, key));
if (!b)
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_KEY_NOT_FOUND,
"key doesn't exist");
ix = b - hash->bs;
}
else
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"unhandled type aggregate");
ix /= 3;
}
else
ix = VTABLE_get_integer(interp, key);
return ix;
}
/*
=item C<static char *
char_offset_key(PARROT_INTERP, PMC *pmc, PMC *key, int *type)>
Returns the pointer for the element associated with key C<*key>, and
sets the element type in C<*type>.
=cut
*/
static char *
char_offset_key(PARROT_INTERP, PMC *pmc, PMC *key, int *type)
{
size_t offs, count, size, max;
int ix;
PMC *next, *init;
char *p;
#ifdef STRUCT_DEBUG
trace_key_dump(interp, key);
#endif
ix = key_2_idx(interp, pmc, key);
next = key_next(interp, key);
p = char_offset_int(interp, pmc, ix, type);
ix *= 3;
if (!next)
return p;
if (PObj_get_FLAGS(next) & KEY_integer_FLAG)
count = VTABLE_get_integer(interp, next);
else
count = 1;
init = PARROT_UNMANAGEDSTRUCT(pmc)->init;
max = (size_t)VTABLE_get_integer_keyed_int(interp, init, ix + 1);
#ifdef STRUCT_DEBUG
Parrot_io_eprintf(interp, " count = %d ix = %d max = %d\n",
(int)count, (int)ix, (int)max);
#endif
if (*type == enum_type_struct_ptr || *type == enum_type_struct) {
/* the struct PMC is hanging off the initializer element
* as property "_struct" */
PMC * const ptr = VTABLE_get_pmc_keyed_int(interp, init, ix);
init = VTABLE_getprop(interp, ptr, CONST_STRING(interp, "_struct"));
PARROT_ASSERT(init
&& (init->vtable->base_type == enum_class_UnManagedStruct
|| init->vtable->base_type == enum_class_ManagedStruct));
/* array of structs */
if (max > 1) {
if (key_next(interp, next))
next = key_next(interp, next);
offs = VTABLE_get_integer(interp, init);
#ifdef STRUCT_DEBUG
Parrot_io_eprintf(interp, "offs = %d\n", (int)offs);
#endif
p += offs * count;
}
if (init->vtable->base_type == enum_class_UnManagedStruct) {
/* now point ptr to the real data */
if (*type == enum_type_struct_ptr) {
/* that is either a pointer */
PARROT_ASSERT((PTR2INTVAL(p) & (PARROT_PTR_ALIGNMENT - 1)) == 0);
VTABLE_set_pointer(interp, init, *(void**)p);
}
/* or just an offset for nested structs */
else
VTABLE_set_pointer(interp, init, p);
}
else if (init->vtable->base_type == enum_class_ManagedStruct
&& *type == enum_type_struct_ptr) {
/* a nested struct pointer belonging to us
* p is the location of the struct pointer in the
* outer struct, the inner is at PMC_data(init) */
PARROT_ASSERT((PTR2INTVAL(p) & (PARROT_PTR_ALIGNMENT - 1)) == 0);
*(void **)p = VTABLE_get_pointer(interp, init);
}
return char_offset_key(interp, init, next, type);
}
if (count >= max)
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_OUT_OF_BOUNDS,
"Non existent array element in struct: "
"count = %d max=%d", (int)count, (int)max);
size = data_types[*type - enum_first_type].size;
return p + count * size;
}
/*
=item C<static INTVAL
ret_int(PARROT_INTERP, const char *p, int type)>
Returns the element of type C<type> starting at C<*p> as an C<INTVAL>.
If, for example, C<char> or c<short> type size doesn't match, this will fail
we need some more configure support for type sizes.
=cut
*/
static INTVAL
ret_int(PARROT_INTERP, const char *p, int type)
__attribute__nonnull__(1);
static INTVAL
ret_int(PARROT_INTERP, const char *p, int type)
{
switch (type) {
case enum_type_INTVAL:
return *(const INTVAL*) p;
#if INT_SIZE == 4
case enum_type_int32:
case enum_type_uint32:
#endif
#if INT_SIZE == 8
case enum_type_int64:
case enum_type_uint64:
#endif
case enum_type_int:
return *(const int *)p;
#if (LONG_SIZE == 4) && !(INT_SIZE == 4) /* Unlikely combination. */
case enum_type_int32:
case enum_type_uint32:
#endif
#if (LONG_SIZE == 8) && !(INT_SIZE == 8)
case enum_type_int64:
case enum_type_uint64:
#endif
case enum_type_long:
case enum_type_ulong:
return *(const long *)p;
#if SHORT_SIZE == 2
case enum_type_int16:
case enum_type_uint16:
#endif
/* If SHORT_SIZE != 2 getting int16s requires extra tricks. */
case enum_type_short:
return *(const short *)p;
case enum_type_uint8:
case enum_type_uchar:
{
const unsigned char *uc = (const unsigned char *)p;
return (INTVAL)*uc;
}
case enum_type_int8:
case enum_type_char:
return *p;
default:
Parrot_ex_throw_from_c_args(interp, NULL, 1,
"returning unhandled int type in struct");
}
}
/*
=item C<static FLOATVAL
ret_float(PARROT_INTERP, const char *p, int type)>
Returns the element of type C<type> starting at C<*p> as a C<FLOATVAL>.
=cut
*/
static FLOATVAL
ret_float(PARROT_INTERP, const char *p, int type)
__attribute__nonnull__(1);
static FLOATVAL
ret_float(PARROT_INTERP, const char *p, int type)
{
switch (type) {
case enum_type_FLOATVAL:
return (FLOATVAL) *(const FLOATVAL *)p;
case enum_type_float:
return (FLOATVAL) *(const float *)p;
case enum_type_double:
return (FLOATVAL) *(const double *)p;
default:
Parrot_ex_throw_from_c_args(interp, NULL, 1,
"returning unhandled float type in struct");
}
}
/*
=item C<static STRING*
ret_string(PARROT_INTERP, char *p, int type)>
Returns the element of type C<type> starting at C<*p> as a Parrot string.
=cut
*/
static STRING*
ret_string(PARROT_INTERP, char *p, int type)
{
if (type == enum_type_cstr) {
char *cstr = *(char **) p;
if (cstr) {
size_t len = strlen(cstr);
/* TODO
Can't assume that the C string is constant during the
life of the returned parrot string, so can't be
flagged as external in general.
If avoid the copy for speed reasons is a concern,
other type or flag must be added.
Need to provide some way to specify charset and encoding.
*/
return string_make(interp, cstr, len, "iso-8859-1", 0);
}
else
return NULL;
}
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"returning unhandled string type in struct");
}
/*
=item C<static PMC*
ret_pmc(PARROT_INTERP, PMC *pmc, char *p, int type, INTVAL idx)>
Returns the element of type C<type> starting at C<*p> as a PMC.
=cut
*/
static PMC*
ret_pmc(PARROT_INTERP, PMC *pmc, char *p, int type, INTVAL idx)
{
PMC *ret = NULL;
PMC *init = PARROT_UNMANAGEDSTRUCT(pmc)->init;
PMC *ptr = VTABLE_get_pmc_keyed_int(interp, init, idx * 3);
switch (type) {
case enum_type_func_ptr:
/* this is a raw function pointer - not a PMC */
ret = *(PMC**) p;
/* now check if initializer has a signature attached */
if (PMC_metadata(ptr)) {
STRING *signature_str = CONST_STRING(interp, "_signature");
PMC *sig = VTABLE_getprop(interp, ptr, signature_str);
if (VTABLE_defined(interp, sig)) {
STRING *sig_str = VTABLE_get_string(interp, sig);
ret = pmc_new(interp, enum_class_NCI);
VTABLE_set_pointer_keyed_str(interp, ret, sig_str,
*(PMC **)p);
}
}
return ret;
case enum_type_struct_ptr:
/* check the metadata for an initializer */
/* grab the struct from the metadata */
if (PMC_metadata(ptr))
ret = VTABLE_getprop(interp, ptr, CONST_STRING(interp, "_struct"));
else {
Parrot_ex_throw_from_c_args(interp, NULL,
EXCEPTION_INVALID_OPERATION,
"no initializer available for nested struct");
}
VTABLE_set_pointer(interp, ret, *(void**)p);
return ret;
default:
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"returning unhandled pmc type (%d) in struct", type);
}
}
/*
=item C<static void
set_int(PARROT_INTERP, char *p, int type, INTVAL value)>
=cut
*/
static void
set_int(PARROT_INTERP, char *p, int type, INTVAL value)
{
switch (type) {
case enum_type_uint8:
case enum_type_int8:
case enum_type_char:
case enum_type_uchar:
*(char *)p = (char)(value & 0xff);
break;
case enum_type_INTVAL:
*(INTVAL *)p = value;
break;
case enum_type_int:
*(int *)p = value;
break;
case enum_type_int16:
case enum_type_uint16:
case enum_type_short:
*(short *)p = (short)value;
break;
default:
Parrot_ex_throw_from_c_args(interp, NULL, 1,
"setting unhandled int type in struct");
break;
}
}
/*
=item C<static void
set_float(PARROT_INTERP, char *p, int type, FLOATVAL value)>
Sets the value of the element of type C<type> starting at C<*p> to
C<value>.
=cut
*/
static void
set_float(PARROT_INTERP, char *p, int type, FLOATVAL value)
{
switch (type) {
case enum_type_FLOATVAL:
*(FLOATVAL *)p = (FLOATVAL)value;
break;
case enum_type_float:
*(float *)p = (float)value;
break;
case enum_type_double:
*(double *)p = (double)value;
break;
default:
Parrot_ex_throw_from_c_args(interp, NULL, 1,
"setting unhandled float type in struct");
break;
}
}
/*
=item C<static void
set_string(PARROT_INTERP, char *p, int type, STRING *value)>
Sets the value of the element of type C<type> starting at C<*p> to
C<*value>.
=cut
*/
static void
set_string(PARROT_INTERP, char *p, int type, STRING *value)
{
if (type == enum_type_cstr) {
/* assuming 0-terminated C-string here;
* we can't use Parrot_str_to_cstring easily */
char *cstr = (char *)Buffer_bufstart(value);
*(char **)p = cstr;
}
else
Parrot_ex_throw_from_c_args(interp, NULL, 1,
"setting unhandled string type in struct (%d)", type);
}
/*
=item C<static int
calc_align(PARROT_INTERP, PMC *pmc, PMC *type_pmc,
int type, size_t offs)>
Alignment of contained structures is the alignment of the biggest item in that
C<struct>.
i386: C<long long> or C<double> is aligned on 4.
This is recursive as structure definitions.
=cut
*/
static int
calc_align(PARROT_INTERP, PMC *pmc, PMC *type_pmc,
int type, size_t offs)
{
int align = data_types[type - enum_first_type].size;
PMC *nested = NULL;
PMC *nested_init = NULL;
if (type == enum_type_struct || type == enum_type_struct_ptr) {
/* a nested structs alignment is the biggest item in it
* so go through that struct and check */
nested = VTABLE_getprop(interp, type_pmc, CONST_STRING(interp, "_struct"));
nested_init = PARROT_UNMANAGEDSTRUCT(nested)->init;
}
if (type == enum_type_struct) {
INTVAL i, n = (size_t)VTABLE_elements(interp, nested_init);
int a_max = 0;
int new_offs;
if (n % 3)
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"Illegal initializer for struct");
for (i = 0; i < n; i += 3) {
PMC *nested_type_pmc = VTABLE_get_pmc_keyed_int(interp,
nested_init, i);
int nested_type = (int)VTABLE_get_integer(interp,
nested_type_pmc);
new_offs = calc_align(interp, nested,
nested_type_pmc, nested_type, offs);
if (new_offs > a_max)
a_max = new_offs;
}
align = a_max;
}
if (align && offs % align) {
const int diff = align - (offs % align);
offs += diff;
}
if (type == enum_type_struct || type == enum_type_struct_ptr)
calc_offsets(interp, nested, nested_init, 0);
return offs;
}
/*
=item C<static size_t
calc_offsets(PARROT_INTERP, PMC *pmc, PMC *value, size_t toff)>
Calculates the offsets for the C<struct>. See C<init_pmc()> for a description
of C<*value>.
=cut
*/
static size_t
calc_offsets(PARROT_INTERP, PMC *pmc, PMC *value, size_t toff)
{
STRING *_struct = CONST_STRING(interp, "_struct");
INTVAL n = (size_t)VTABLE_elements(interp, value);
INTVAL i;
int size;
if (n % 3)
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"Illegal initializer for struct");
for (i = 0; i < n; i += 3) {
PMC *type_pmc = VTABLE_get_pmc_keyed_int(interp, value, i);
int type = (int)VTABLE_get_integer(interp, type_pmc);
int count = (int)VTABLE_get_integer_keyed_int(interp, value, i + 1);
int offs = (int)VTABLE_get_integer_keyed_int(interp, value, i + 2);
if (type < enum_first_type || type >= enum_last_type)
Parrot_ex_throw_from_c_args(interp, NULL,
EXCEPTION_INVALID_OPERATION,
"Illegal type in initializer for struct");
if (count <= 0) {
count = 1;
VTABLE_set_integer_keyed_int(interp, value, i + 1, count);
}
if (offs <= 0) {
offs = toff = calc_align(interp, pmc, type_pmc, type, toff);
VTABLE_set_integer_keyed_int(interp, value, i + 2, offs);
}
else
toff = offs;
if (type == enum_type_struct) {
PMC *nested = VTABLE_getprop(interp, type_pmc, _struct);
size = VTABLE_get_integer(interp, nested);
}
else if (type == enum_type_struct_ptr) {
PMC *nested = VTABLE_getprop(interp, type_pmc, _struct);
/* must clone this struct so as not to share its memory */
if (nested->vtable->base_type == enum_class_ManagedStruct)
VTABLE_setprop(interp, type_pmc, _struct,
VTABLE_clone(interp, nested));
size = data_types[type - enum_first_type].size;
}
else
size = data_types[type - enum_first_type].size;
toff += count * size;
/* set / allocate size */
if (i == n - 3)
VTABLE_set_integer_native(interp, pmc, (INTVAL)toff);
}
return toff;
}
pmclass UnManagedStruct auto_attrs no_ro {
ATTR void *ptr; /* the struct that this UnManagedStruct isn't managing */
ATTR PMC *init; /* the initializer used with this UnManagedStruct */
ATTR INTVAL size; /* the size of the struct */
/*
=back
=head2 Methods
=over 4
=item C<void init_pmc(PMC *value)>
Initialize the struct with some data.
C<*value> should be an array of triples of:
=over 4
=item 0
The datatype. See the C<enum> in F<include/parrot/datatypes.h>.
=item 1
The count.
=item 2
The offset.
=back
=cut
*/
VTABLE void init_pmc(PMC *value) {
SELF.set_pmc(value);
}
/*
=item C<PMC *clone()>
Return a clone of this PMC.
=cut
*/
VTABLE PMC *clone() {
PMC *clone = pmc_new(INTERP, enum_class_UnManagedStruct);
mem_sys_memmove(PMC_data(clone), PMC_data(SELF),
sizeof (Parrot_UnManagedStruct_attributes));
PARROT_UNMANAGEDSTRUCT(clone)->init =
VTABLE_clone(INTERP, PARROT_UNMANAGEDSTRUCT(SELF)->init);
return clone;
}
/*
=item C<void set_pmc(PMC *value)>
Sets C<*value> (see C<init_pmc()> and calculates the offsets.
=cut
*/
VTABLE void set_pmc(PMC *value) {
PARROT_UNMANAGEDSTRUCT(SELF)->init = value;
PObj_custom_mark_SET(SELF);
calc_offsets(INTERP, SELF, value, 0);
}
/*
=item C<void mark()>
Marks the C<struct> as live.
=cut
*/
VTABLE void mark() {
PMC *init = PARROT_UNMANAGEDSTRUCT(SELF)->init;
Parrot_gc_mark_PMC_alive(INTERP, init);
}
/*
=item C<INTVAL is_equal(PMC *value)>
Returns whether the two C<struct>s are equivalent.
=cut
*/
VTABLE INTVAL is_equal(PMC *value) {
return (SELF->vtable == value->vtable
&& SELF.get_pointer() == VTABLE_get_pointer(interp, value));
}
/*
=item C<INTVAL defined()>
Returns whether the C<struct> is defined.
=cut
*/
VTABLE INTVAL defined() {
return SELF.get_pointer() != NULL;
}
/*
=item C<INTVAL get_integer()>
Returns the size of the C<struct>.
=cut
*/
VTABLE INTVAL get_integer() {
return PARROT_UNMANAGEDSTRUCT(SELF)->size;
}
/*
=item C<void set_integer_native(INTVAL size)>
Sets the size of the C<struct>.
=cut
*/
VTABLE void set_integer_native(INTVAL size) {
PARROT_UNMANAGEDSTRUCT(SELF)->size = size;
}
/*
=item C<INTVAL get_integer_keyed_int(INTVAL ix)>
Returns the integer value at index C<ix>.
=cut
*/
VTABLE INTVAL get_integer_keyed_int(INTVAL ix) {
int type;
char *p = char_offset_int(INTERP, pmc, ix, &type);
return ret_int(INTERP, p, type);
}
/*
=item C<INTVAL get_integer_keyed(PMC *key)>
Returns the integer value associated with C<*key>.
=cut
*/
VTABLE INTVAL get_integer_keyed(PMC *key) {
int type;
char *p = char_offset_key(INTERP, pmc, key, &type);
return ret_int(INTERP, p, type);
}
/*
=item C<FLOATVAL get_number_keyed_int(INTVAL key)>
Returns the floating-point value at index C<ix>.
=cut
*/
VTABLE FLOATVAL get_number_keyed_int(INTVAL key) {
int type;
char *p = char_offset_int(INTERP, pmc, key, &type);
return ret_float(INTERP, p, type);
}
/*
=item C<FLOATVAL get_number_keyed(PMC *key)>
Returns the floating-point value associated with C<*key>.
=cut
*/
VTABLE FLOATVAL get_number_keyed(PMC *key) {
int type;
char *p = char_offset_key(INTERP, pmc, key, &type);
return ret_float(INTERP, p, type);
}
/*
=item C<STRING *get_string_keyed_int(INTVAL key)>
Returns the Parrot string value at index C<ix>.
=cut
*/
VTABLE STRING *get_string_keyed_int(INTVAL key) {
int type;
char *p = char_offset_int(INTERP, pmc, key, &type);
return ret_string(INTERP, p, type);
}
/*
=item C<STRING *get_string_keyed(PMC *key)>
Returns the Parrot string value associated with C<*key>.
=cut
*/
VTABLE STRING *get_string_keyed(PMC *key) {
int type;
char *p = char_offset_key(INTERP, pmc, key, &type);
return ret_string(INTERP, p, type);
}
/*
=item C<PMC *get_pmc_keyed_int(INTVAL key)>
Returns the PMC value at index C<ix>.
=cut
*/
VTABLE PMC *get_pmc_keyed_int(INTVAL key) {
int type;
char *p = char_offset_int(INTERP, pmc, key, &type);
return ret_pmc(INTERP, pmc, p, type, key);
}
/*
=item C<PMC *get_pmc_keyed(PMC *key)>
Returns the PMC value associated with C<*key>.
=cut
*/
VTABLE PMC *get_pmc_keyed(PMC *key) {
int type;
char *p = char_offset_key(INTERP, pmc, key, &type);
return ret_pmc(INTERP, pmc, p, type, key_2_idx(INTERP, pmc, key));
}
/*
=item C<void *get_pointer()>
Returns the pointer to the actual C C<struct>.
=cut
*/
VTABLE void *get_pointer() {
return PARROT_UNMANAGEDSTRUCT(SELF)->ptr;
}
/*
=item C<void set_pointer(void *value)>
Set the pointer to the actual C C<struct>.
=cut
*/
VTABLE void set_pointer(void *value) {
PARROT_UNMANAGEDSTRUCT(SELF)->ptr = value;
}
/*
=item C<void set_integer_keyed_int(INTVAL ix, INTVAL value)>
Sets the value of the element at index C<ix> to C<value>.
=cut
*/
VTABLE void set_integer_keyed_int(INTVAL ix, INTVAL value) {
int type;
char *p = char_offset_int(INTERP, pmc, ix, &type);
set_int(INTERP, p, type, value);
}
/*
=item C<void set_integer_keyed(PMC *key, INTVAL value)>
Sets the value of the element associated with key C<*key> to C<value>.
May cause segfaults if value is out of bounds.
=cut
*/
VTABLE void set_integer_keyed(PMC *key, INTVAL value) {
int type;
char *p = char_offset_key(INTERP, pmc, key, &type);
set_int(INTERP, p, type, value);
}
/*
=item C<void set_number_keyed_int(INTVAL key, FLOATVAL value)>
Sets the value of the element at index C<ix> to C<value>.
=cut
*/
VTABLE void set_number_keyed_int(INTVAL key, FLOATVAL value) {
int type;
char *p = char_offset_int(INTERP, pmc, key, &type);
set_float(INTERP, p, type, value);
}
/*
=item C<void set_number_keyed(PMC *key, FLOATVAL value)>
Sets the value of the element associated with key C<*key> to C<value>.
=cut
*/
VTABLE void set_number_keyed(PMC *key, FLOATVAL value) {
int type;
char *p = char_offset_key(INTERP, pmc, key, &type);
set_float(INTERP, p, type, value);
}
/*
=item C<void set_string_keyed_int(INTVAL key, STRING *value)>
Sets the value of the element at index C<key> to C<*value>.
=cut
*/
VTABLE void set_string_keyed_int(INTVAL key, STRING *value) {
int type;
char *p = char_offset_int(INTERP, pmc, key, &type);
set_string(INTERP, p, type, value);
}
/*
=item C<void set_string_keyed(PMC *key, STRING *value)>
Sets the value of the element associated with key C<*key> to C<*value>.
=cut
*/
VTABLE void set_string_keyed(PMC *key, STRING *value) {
int type;
char *p = char_offset_key(INTERP, pmc, key, &type);
set_string(INTERP, p, type, value);
}
}
/*
=back
=head1 HISTORY
Initial revision by sean 2002/08/04
=head1 SEE ALSO
F<docs/pmc/struct.pod>
=cut
*/
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4:
*/
Jump to Line
Something went wrong with that request. Please try again.