/* * Copyright (c) 2011 Jiri Svoboda * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file Run-time data representation. * * At run time SBI represents all data as a graph of interconnected @c var * nodes (variable nodes). Any piece of memory addressable by the program * (i.e. all variables) are stored in var nodes. However, var nodes are also * used internally to implement value items. (I.e. values in value items * have exactly the same structure as program variables). * * Unlike byte- or word-oriented memory on a real machine, var nodes provide * structured and typed storage. (This typing is dynamic, however and has * nothing to do with the static type system). * * There are several types of var nodes, one for each primitive type, * reference, delegate, array, and object. A reference var node contains * a pointer to another var node. Delegate var node points to some stree * declaration. Array and object var nodes refer to a collection of child * nodes (fields, elements). */ #include #include #include "bigint.h" #include "list.h" #include "mytypes.h" #include "stree.h" #include "symbol.h" #include "strtab.h" #include "rdata.h" static void rdata_bool_copy(rdata_bool_t *src, rdata_bool_t **dest); static void rdata_char_copy(rdata_char_t *src, rdata_char_t **dest); static void rdata_int_copy(rdata_int_t *src, rdata_int_t **dest); static void rdata_string_copy(rdata_string_t *src, rdata_string_t **dest); static void rdata_ref_copy(rdata_ref_t *src, rdata_ref_t **dest); static void rdata_deleg_copy(rdata_deleg_t *src, rdata_deleg_t **dest); static void rdata_enum_copy(rdata_enum_t *src, rdata_enum_t **dest); static void rdata_array_copy(rdata_array_t *src, rdata_array_t **dest); static void rdata_object_copy(rdata_object_t *src, rdata_object_t **dest); static void rdata_resource_copy(rdata_resource_t *src, rdata_resource_t **dest); static void rdata_symbol_copy(rdata_symbol_t *src, rdata_symbol_t **dest); static void rdata_var_destroy_inner(rdata_var_t *var); static void rdata_bool_destroy(rdata_bool_t *bool_v); static void rdata_char_destroy(rdata_char_t *char_v); static void rdata_int_destroy(rdata_int_t *int_v); static void rdata_string_destroy(rdata_string_t *string_v); static void rdata_ref_destroy(rdata_ref_t *ref_v); static void rdata_deleg_destroy(rdata_deleg_t *deleg_v); static void rdata_enum_destroy(rdata_enum_t *enum_v); static void rdata_array_destroy(rdata_array_t *array_v); static void rdata_object_destroy(rdata_object_t *object_v); static void rdata_resource_destroy(rdata_resource_t *resource_v); static void rdata_symbol_destroy(rdata_symbol_t *symbol_v); static int rdata_array_get_dim(rdata_array_t *array); static void rdata_var_copy_to(rdata_var_t *src, rdata_var_t *dest); static void rdata_address_print(rdata_address_t *address); static void rdata_var_print(rdata_var_t *var); /** Allocate new data item. * * @param ic Item class. * @return New item. */ rdata_item_t *rdata_item_new(item_class_t ic) { rdata_item_t *item; item = calloc(1, sizeof(rdata_item_t)); if (item == NULL) { printf("Memory allocation failed.\n"); exit(1); } item->ic = ic; return item; } /** Allocate new address. * * @return New address. */ rdata_addr_var_t *rdata_addr_var_new(void) { rdata_addr_var_t *addr_var; addr_var = calloc(1, sizeof(rdata_addr_var_t)); if (addr_var == NULL) { printf("Memory allocation failed.\n"); exit(1); } return addr_var; } /** Allocate new named property address. * * @return New named property address. */ rdata_aprop_named_t *rdata_aprop_named_new(void) { rdata_aprop_named_t *aprop_named; aprop_named = calloc(1, sizeof(rdata_aprop_named_t)); if (aprop_named == NULL) { printf("Memory allocation failed.\n"); exit(1); } return aprop_named; } /** Allocate new indexed property address. * * @return New indexed property address. */ rdata_aprop_indexed_t *rdata_aprop_indexed_new(void) { rdata_aprop_indexed_t *aprop_indexed; aprop_indexed = calloc(1, sizeof(rdata_aprop_indexed_t)); if (aprop_indexed == NULL) { printf("Memory allocation failed.\n"); exit(1); } return aprop_indexed; } /** Allocate new property address. * * @param apc Property address class. * @return New property address. */ rdata_addr_prop_t *rdata_addr_prop_new(aprop_class_t apc) { rdata_addr_prop_t *addr_prop; addr_prop = calloc(1, sizeof(rdata_addr_prop_t)); if (addr_prop == NULL) { printf("Memory allocation failed.\n"); exit(1); } addr_prop->apc = apc; return addr_prop; } /** Allocate new address. * * @param ac Address class. * @return New address. */ rdata_address_t *rdata_address_new(address_class_t ac) { rdata_address_t *address; address = calloc(1, sizeof(rdata_address_t)); if (address == NULL) { printf("Memory allocation failed.\n"); exit(1); } address->ac = ac; return address; } /** Allocate new value. * * @return New value. */ rdata_value_t *rdata_value_new(void) { rdata_value_t *value; value = calloc(1, sizeof(rdata_value_t)); if (value == NULL) { printf("Memory allocation failed.\n"); exit(1); } return value; } /** Allocate new var node. * * @param vc Var node class (varclass). * @return New var node. */ rdata_var_t *rdata_var_new(var_class_t vc) { rdata_var_t *var; var = calloc(1, sizeof(rdata_var_t)); if (var == NULL) { printf("Memory allocation failed.\n"); exit(1); } var->vc = vc; return var; } /** Allocate new reference. * * @return New reference. */ rdata_ref_t *rdata_ref_new(void) { rdata_ref_t *ref; ref = calloc(1, sizeof(rdata_ref_t)); if (ref == NULL) { printf("Memory allocation failed.\n"); exit(1); } return ref; } /** Allocate new delegate. * * @return New delegate. */ rdata_deleg_t *rdata_deleg_new(void) { rdata_deleg_t *deleg; deleg = calloc(1, sizeof(rdata_deleg_t)); if (deleg == NULL) { printf("Memory allocation failed.\n"); exit(1); } return deleg; } /** Allocate new enum value. * * @return New enum value. */ rdata_enum_t *rdata_enum_new(void) { rdata_enum_t *enum_v; enum_v = calloc(1, sizeof(rdata_enum_t)); if (enum_v == NULL) { printf("Memory allocation failed.\n"); exit(1); } return enum_v; } /** Allocate new array. * * @return New array. */ rdata_array_t *rdata_array_new(int rank) { rdata_array_t *array; array = calloc(1, sizeof(rdata_array_t)); if (array == NULL) { printf("Memory allocation failed.\n"); exit(1); } array->rank = rank; array->extent = calloc(rank, sizeof(int)); if (array == NULL) { printf("Memory allocation failed.\n"); exit(1); } return array; } /** Allocate new object. * * @return New object. */ rdata_object_t *rdata_object_new(void) { rdata_object_t *object; object = calloc(1, sizeof(rdata_object_t)); if (object == NULL) { printf("Memory allocation failed.\n"); exit(1); } return object; } /** Allocate new boolean. * * @return New boolean. */ rdata_bool_t *rdata_bool_new(void) { rdata_bool_t *bool_v; bool_v = calloc(1, sizeof(rdata_bool_t)); if (bool_v == NULL) { printf("Memory allocation failed.\n"); exit(1); } return bool_v; } /** Allocate new character. * * @return New character. */ rdata_char_t *rdata_char_new(void) { rdata_char_t *char_v; char_v = calloc(1, sizeof(rdata_char_t)); if (char_v == NULL) { printf("Memory allocation failed.\n"); exit(1); } return char_v; } /** Allocate new integer. * * @return New integer. */ rdata_int_t *rdata_int_new(void) { rdata_int_t *int_v; int_v = calloc(1, sizeof(rdata_int_t)); if (int_v == NULL) { printf("Memory allocation failed.\n"); exit(1); } return int_v; } /** Allocate new string. * * @return New string. */ rdata_string_t *rdata_string_new(void) { rdata_string_t *string_v; string_v = calloc(1, sizeof(rdata_string_t)); if (string_v == NULL) { printf("Memory allocation failed.\n"); exit(1); } return string_v; } /** Allocate new resource. * * @return New resource. */ rdata_resource_t *rdata_resource_new(void) { rdata_resource_t *resource_v; resource_v = calloc(1, sizeof(rdata_resource_t)); if (resource_v == NULL) { printf("Memory allocation failed.\n"); exit(1); } return resource_v; } /** Allocate new symbol reference. * * @return New symbol reference. */ rdata_symbol_t *rdata_symbol_new(void) { rdata_symbol_t *symbol_v; symbol_v = calloc(1, sizeof(rdata_symbol_t)); if (symbol_v == NULL) { printf("Memory allocation failed.\n"); exit(1); } return symbol_v; } /** Allocate array elements. * * Allocates element array of @a array. * * @param array Array. */ void rdata_array_alloc_element(rdata_array_t *array) { int dim; dim = rdata_array_get_dim(array); array->element = calloc(dim, sizeof(rdata_var_t *)); if (array->element == NULL) { printf("Memory allocation failed.\n"); exit(1); } } /** Get array dimension. * * Dimension is the total number of elements in an array, in other words, * the product of all extents. * * @param array Array. */ static int rdata_array_get_dim(rdata_array_t *array) { int didx, dim; dim = 1; for (didx = 0; didx < array->rank; ++didx) dim = dim * array->extent[didx]; return dim; } /** Deallocate item. * * @param item Item node */ void rdata_item_delete(rdata_item_t *item) { assert(item != NULL); free(item); } /** Deallocate variable address. * * @param addr_var Variable address node */ void rdata_addr_var_delete(rdata_addr_var_t *addr_var) { assert(addr_var != NULL); free(addr_var); } /** Deallocate property address. * * @param addr_prop Variable address node */ void rdata_addr_prop_delete(rdata_addr_prop_t *addr_prop) { assert(addr_prop != NULL); free(addr_prop); } /** Deallocate named property address. * * @param aprop_named Variable address node */ void rdata_aprop_named_delete(rdata_aprop_named_t *aprop_named) { assert(aprop_named != NULL); free(aprop_named); } /** Deallocate indexed property address. * * @param aprop_indexed Variable address node */ void rdata_aprop_indexed_delete(rdata_aprop_indexed_t *aprop_indexed) { assert(aprop_indexed != NULL); free(aprop_indexed); } /** Deallocate address. * * @param address Address node */ void rdata_address_delete(rdata_address_t *address) { assert(address != NULL); free(address); } /** Deallocate value. * * @param value Value node */ void rdata_value_delete(rdata_value_t *value) { assert(value != NULL); free(value); } /** Deallocate var node. * * @param var Var node */ void rdata_var_delete(rdata_var_t *var) { assert(var != NULL); free(var); } /** Deallocate boolean. * * @param bool_v Boolean */ void rdata_bool_delete(rdata_bool_t *bool_v) { assert(bool_v != NULL); free(bool_v); } /** Deallocate character. * * @param char_v Character */ void rdata_char_delete(rdata_char_t *char_v) { assert(char_v != NULL); free(char_v); } /** Deallocate integer. * * @param int_v Integer */ void rdata_int_delete(rdata_int_t *int_v) { assert(int_v != NULL); free(int_v); } /** Deallocate string. * * @param string_v String */ void rdata_string_delete(rdata_string_t *string_v) { assert(string_v != NULL); free(string_v); } /** Deallocate reference. * * @param ref_v Reference */ void rdata_ref_delete(rdata_ref_t *ref_v) { assert(ref_v != NULL); free(ref_v); } /** Deallocate delegate. * * @param deleg_v Reference */ void rdata_deleg_delete(rdata_deleg_t *deleg_v) { assert(deleg_v != NULL); free(deleg_v); } /** Deallocate enum. * * @param enum_v Reference */ void rdata_enum_delete(rdata_enum_t *enum_v) { assert(enum_v != NULL); free(enum_v); } /** Deallocate array. * * @param array_v Array */ void rdata_array_delete(rdata_array_t *array_v) { assert(array_v != NULL); free(array_v); } /** Deallocate object. * * @param object_v Object */ void rdata_object_delete(rdata_object_t *object_v) { assert(object_v != NULL); free(object_v); } /** Deallocate resource. * * @param resource_v Resource */ void rdata_resource_delete(rdata_resource_t *resource_v) { assert(resource_v != NULL); free(resource_v); } /** Deallocate symbol. * * @param symbol_v Symbol */ void rdata_symbol_delete(rdata_symbol_t *symbol_v) { assert(symbol_v != NULL); free(symbol_v); } /** Copy value. * * @param src Input value * @param dest Place to store pointer to new value */ void rdata_value_copy(rdata_value_t *src, rdata_value_t **dest) { assert(src != NULL); *dest = rdata_value_new(); rdata_var_copy(src->var, &(*dest)->var); } /** Make copy of a variable. * * Creates a new var node that is an exact copy of an existing var node. * This can be thought of as a shallow copy. * * @param src Source var node. * @param dest Place to store pointer to new var node. */ void rdata_var_copy(rdata_var_t *src, rdata_var_t **dest) { rdata_var_t *nvar; nvar = rdata_var_new(src->vc); rdata_var_copy_to(src, nvar); *dest = nvar; } /** Copy variable content to another variable. * * Writes an exact copy of an existing var node to another var node. * The varclass of @a src and @a dest must match. The content of * @a dest.u must be invalid. * * @param src Source var node. * @param dest Destination var node. */ static void rdata_var_copy_to(rdata_var_t *src, rdata_var_t *dest) { dest->vc = src->vc; switch (src->vc) { case vc_bool: rdata_bool_copy(src->u.bool_v, &dest->u.bool_v); break; case vc_char: rdata_char_copy(src->u.char_v, &dest->u.char_v); break; case vc_int: rdata_int_copy(src->u.int_v, &dest->u.int_v); break; case vc_string: rdata_string_copy(src->u.string_v, &dest->u.string_v); break; case vc_ref: rdata_ref_copy(src->u.ref_v, &dest->u.ref_v); break; case vc_deleg: rdata_deleg_copy(src->u.deleg_v, &dest->u.deleg_v); break; case vc_enum: rdata_enum_copy(src->u.enum_v, &dest->u.enum_v); break; case vc_array: rdata_array_copy(src->u.array_v, &dest->u.array_v); break; case vc_object: rdata_object_copy(src->u.object_v, &dest->u.object_v); break; case vc_resource: rdata_resource_copy(src->u.resource_v, &dest->u.resource_v); break; case vc_symbol: rdata_symbol_copy(src->u.symbol_v, &dest->u.symbol_v); break; } } /** Copy boolean. * * @param src Source boolean * @param dest Place to store pointer to new boolean */ static void rdata_bool_copy(rdata_bool_t *src, rdata_bool_t **dest) { *dest = rdata_bool_new(); (*dest)->value = src->value; } /** Copy character. * * @param src Source character * @param dest Place to store pointer to new character */ static void rdata_char_copy(rdata_char_t *src, rdata_char_t **dest) { *dest = rdata_char_new(); bigint_clone(&src->value, &(*dest)->value); } /** Copy integer. * * @param src Source integer * @param dest Place to store pointer to new integer */ static void rdata_int_copy(rdata_int_t *src, rdata_int_t **dest) { *dest = rdata_int_new(); bigint_clone(&src->value, &(*dest)->value); } /** Copy string. * * @param src Source string. * @param dest Place to store pointer to new string. */ static void rdata_string_copy(rdata_string_t *src, rdata_string_t **dest) { *dest = rdata_string_new(); (*dest)->value = src->value; } /** Copy reference. * * @param src Source reference. * @param dest Place to store pointer to new reference. */ static void rdata_ref_copy(rdata_ref_t *src, rdata_ref_t **dest) { *dest = rdata_ref_new(); (*dest)->vref = src->vref; } /** Copy delegate. * * @param src Source delegate. * @param dest Place to store pointer to new delegate. */ static void rdata_deleg_copy(rdata_deleg_t *src, rdata_deleg_t **dest) { *dest = rdata_deleg_new(); (*dest)->obj = src->obj; (*dest)->sym = src->sym; } /** Copy enum value. * * @param src Source enum value. * @param dest Place to store pointer to new enum value. */ static void rdata_enum_copy(rdata_enum_t *src, rdata_enum_t **dest) { *dest = rdata_enum_new(); (*dest)->value = src->value; } /** Copy array. * * @param src Source array. * @param dest Place to store pointer to new array. */ static void rdata_array_copy(rdata_array_t *src, rdata_array_t **dest) { (void) src; (void) dest; printf("Unimplemented: Copy array.\n"); exit(1); } /** Copy object. * * @param src Source object. * @param dest Place to store pointer to new object. */ static void rdata_object_copy(rdata_object_t *src, rdata_object_t **dest) { (void) src; (void) dest; printf("Unimplemented: Copy object.\n"); abort(); } /** Copy resource. * * @param src Source resource. * @param dest Place to store pointer to new resource. */ static void rdata_resource_copy(rdata_resource_t *src, rdata_resource_t **dest) { *dest = rdata_resource_new(); (*dest)->data = src->data; } /** Copy symbol. * * @param src Source symbol. * @param dest Place to store pointer to new symbol. */ static void rdata_symbol_copy(rdata_symbol_t *src, rdata_symbol_t **dest) { *dest = rdata_symbol_new(); (*dest)->sym = src->sym; } /** Destroy var node. * * @param var Var node */ void rdata_var_destroy(rdata_var_t *var) { /* First destroy class-specific part */ rdata_var_destroy_inner(var); /* Deallocate var node */ rdata_var_delete(var); } /** Destroy inside of var node. * * Destroy content of var node, but do not deallocate the var node * itself. * * @param var Var node */ static void rdata_var_destroy_inner(rdata_var_t *var) { /* First destroy class-specific part */ switch (var->vc) { case vc_bool: rdata_bool_destroy(var->u.bool_v); break; case vc_char: rdata_char_destroy(var->u.char_v); break; case vc_int: rdata_int_destroy(var->u.int_v); break; case vc_string: rdata_string_destroy(var->u.string_v); break; case vc_ref: rdata_ref_destroy(var->u.ref_v); break; case vc_deleg: rdata_deleg_destroy(var->u.deleg_v); break; case vc_enum: rdata_enum_destroy(var->u.enum_v); break; case vc_array: rdata_array_destroy(var->u.array_v); break; case vc_object: rdata_object_destroy(var->u.object_v); break; case vc_resource: rdata_resource_destroy(var->u.resource_v); break; case vc_symbol: rdata_symbol_destroy(var->u.symbol_v); break; } } /** Destroy item. * * Destroy an item including the value or address within. * * @param item Item */ void rdata_item_destroy(rdata_item_t *item) { /* First destroy class-specific part */ switch (item->ic) { case ic_address: rdata_address_destroy(item->u.address); break; case ic_value: rdata_value_destroy(item->u.value); break; } /* Deallocate item node */ rdata_item_delete(item); } /** Destroy address. * * Destroy an address node. * * @param address Address */ void rdata_address_destroy(rdata_address_t *address) { switch (address->ac) { case ac_var: rdata_addr_var_destroy(address->u.var_a); break; case ac_prop: rdata_addr_prop_destroy(address->u.prop_a); break; } /* Deallocate address node */ rdata_address_delete(address); } /** Destroy variable address. * * Destroy a variable address node. * * @param addr_var Variable address */ void rdata_addr_var_destroy(rdata_addr_var_t *addr_var) { addr_var->vref = NULL; /* Deallocate variable address node */ rdata_addr_var_delete(addr_var); } /** Destroy property address. * * Destroy a property address node. * * @param addr_prop Property address */ void rdata_addr_prop_destroy(rdata_addr_prop_t *addr_prop) { switch (addr_prop->apc) { case apc_named: rdata_aprop_named_destroy(addr_prop->u.named); break; case apc_indexed: rdata_aprop_indexed_destroy(addr_prop->u.indexed); break; } if (addr_prop->tvalue != NULL) { rdata_value_destroy(addr_prop->tvalue); addr_prop->tvalue = NULL; } addr_prop->tpos = NULL; /* Deallocate property address node */ rdata_addr_prop_delete(addr_prop); } /** Destroy named property address. * * Destroy a named property address node. * * @param aprop_named Named property address */ void rdata_aprop_named_destroy(rdata_aprop_named_t *aprop_named) { rdata_deleg_destroy(aprop_named->prop_d); /* Deallocate named property address node */ rdata_aprop_named_delete(aprop_named); } /** Destroy indexed property address. * * Destroy a indexed property address node. * * @param aprop_indexed Indexed property address */ void rdata_aprop_indexed_destroy(rdata_aprop_indexed_t *aprop_indexed) { list_node_t *arg_node; rdata_item_t *arg_i; /* Destroy the object delegate. */ rdata_deleg_destroy(aprop_indexed->object_d); /* * Walk through all argument items (indices) and destroy them, * removing them from the list as well. */ while (!list_is_empty(&aprop_indexed->args)) { arg_node = list_first(&aprop_indexed->args); arg_i = list_node_data(arg_node, rdata_item_t *); rdata_item_destroy(arg_i); list_remove(&aprop_indexed->args, arg_node); } /* Destroy the now empty list */ list_fini(&aprop_indexed->args); /* Deallocate indexed property address node */ rdata_aprop_indexed_delete(aprop_indexed); } /** Destroy value. * * Destroy a value node. * * @param value Value */ void rdata_value_destroy(rdata_value_t *value) { /* Assumption: Var nodes in values are not shared. */ rdata_var_destroy(value->var); /* Deallocate value node */ rdata_value_delete(value); } /** Destroy boolean. * * @param bool_v Boolean */ static void rdata_bool_destroy(rdata_bool_t *bool_v) { rdata_bool_delete(bool_v); } /** Destroy character. * * @param char_v Character */ static void rdata_char_destroy(rdata_char_t *char_v) { bigint_destroy(&char_v->value); rdata_char_delete(char_v); } /** Destroy integer. * * @param int_v Integer */ static void rdata_int_destroy(rdata_int_t *int_v) { bigint_destroy(&int_v->value); rdata_int_delete(int_v); } /** Destroy string. * * @param string_v String */ static void rdata_string_destroy(rdata_string_t *string_v) { /* * String values are shared so we cannot free them. Just deallocate * the node. */ rdata_string_delete(string_v); } /** Destroy reference. * * @param ref_v Reference */ static void rdata_ref_destroy(rdata_ref_t *ref_v) { ref_v->vref = NULL; rdata_ref_delete(ref_v); } /** Destroy delegate. * * @param deleg_v Reference */ static void rdata_deleg_destroy(rdata_deleg_t *deleg_v) { deleg_v->obj = NULL; deleg_v->sym = NULL; rdata_deleg_delete(deleg_v); } /** Destroy enum. * * @param enum_v Reference */ static void rdata_enum_destroy(rdata_enum_t *enum_v) { enum_v->value = NULL; rdata_enum_delete(enum_v); } /** Destroy array. * * @param array_v Array */ static void rdata_array_destroy(rdata_array_t *array_v) { int d; size_t n_elems, p; /* * Compute total number of elements in array. * At the same time zero out the extent array. */ n_elems = 1; for (d = 0; d < array_v->rank; d++) { n_elems = n_elems * array_v->extent[d]; array_v->extent[d] = 0; } /* Destroy all elements and zero out the array */ for (p = 0; p < n_elems; p++) { rdata_var_delete(array_v->element[p]); array_v->element[p] = NULL; } /* Free the arrays */ free(array_v->element); free(array_v->extent); array_v->rank = 0; /* Deallocate the node */ rdata_array_delete(array_v); } /** Destroy object. * * @param object_v Object */ static void rdata_object_destroy(rdata_object_t *object_v) { /* XXX TODO */ rdata_object_delete(object_v); } /** Destroy resource. * * @param resource_v Resource */ static void rdata_resource_destroy(rdata_resource_t *resource_v) { /* * XXX Presumably this should be handled by the appropriate * built-in module, so, some call-back function would be required. */ resource_v->data = NULL; rdata_resource_delete(resource_v); } /** Destroy symbol. * * @param symbol_v Symbol */ static void rdata_symbol_destroy(rdata_symbol_t *symbol_v) { symbol_v->sym = NULL; rdata_symbol_delete(symbol_v); } /** Read data from a variable. * * This copies data from the variable to a value item. Ideally any read access * to a program variable should go through this function. (Keep in mind * that although values are composed of var nodes internally, but are not * variables per se. Therefore this function is not used to read from values) * * @param var Variable to read from (var node where it is stored). * @param ritem Place to store pointer to new value item read from * the variable. */ void rdata_var_read(rdata_var_t *var, rdata_item_t **ritem) { rdata_value_t *value; rdata_var_t *rvar; /* Perform a shallow copy of @a var. */ rdata_var_copy(var, &rvar); value = rdata_value_new(); value->var = rvar; *ritem = rdata_item_new(ic_value); (*ritem)->u.value = value; } /** Write data to a variable. * * This copies data to the variable from a value. Ideally any write access * to a program variable should go through this function. (Keep in mind * that even though values are composed of var nodes internally, but are not * variables per se. Therefore this function is not used to write to values) * * @param var Variable to write to (var node where it is stored). * @param value The value to write. */ void rdata_var_write(rdata_var_t *var, rdata_value_t *value) { /* Free old content of var->u */ rdata_var_destroy_inner(var); /* Perform a shallow copy of @c value->var. */ rdata_var_copy_to(value->var, var); } /** Print data item in human-readable form. * * @param item Item to print. */ void rdata_item_print(rdata_item_t *item) { if (item == NULL) { printf("none"); return; } switch (item->ic) { case ic_address: printf("address:"); rdata_address_print(item->u.address); break; case ic_value: printf("value:"); rdata_value_print(item->u.value); break; } } /** Print address in human-readable form. * * Actually this displays contents of the var node that is being addressed. * * XXX Maybe we should really rather print the address and not the data * it is pointing to? * * @param item Address to print. */ static void rdata_address_print(rdata_address_t *address) { switch (address->ac) { case ac_var: rdata_var_print(address->u.var_a->vref); break; case ac_prop: printf("Warning: Unimplemented: Print property address.\n"); break; } } /** Print value in human-readable form. * * @param value Value to print. */ void rdata_value_print(rdata_value_t *value) { rdata_var_print(value->var); } /** Print contents of var node in human-readable form. * * @param item Var node to print. */ static void rdata_var_print(rdata_var_t *var) { int val; switch (var->vc) { case vc_bool: printf("bool(%s)", var->u.bool_v->value ? "true" : "false"); break; case vc_char: printf("char("); if (bigint_get_value_int(&var->u.char_v->value, &val) == EOK) printf("'%c'", val); else printf("???:x%x\n", (unsigned) val); printf(")"); break; case vc_int: printf("int("); bigint_print(&var->u.int_v->value); printf(")"); break; case vc_string: printf("string(\"%s\")", var->u.string_v->value); break; case vc_ref: if (var->u.ref_v->vref != NULL) { printf("ref("); rdata_var_print(var->u.ref_v->vref); printf(")"); } else { printf("nil"); } break; case vc_deleg: printf("deleg("); if (var->u.deleg_v->sym != NULL) { if (var->u.deleg_v->obj != NULL) { rdata_var_print(var->u.deleg_v->obj); printf(","); } symbol_print_fqn(var->u.deleg_v->sym); } else { printf("nil"); } printf(")"); break; case vc_enum: symbol_print_fqn( enum_to_symbol(var->u.enum_v->value->outer_enum)); printf(".%s", strtab_get_str(var->u.enum_v->value->name->sid)); break; case vc_array: printf("array"); break; case vc_object: printf("object"); break; case vc_resource: printf("resource(%p)", var->u.resource_v->data); break; case vc_symbol: printf("symbol("); if (var->u.symbol_v->sym != NULL) { symbol_print_fqn(var->u.symbol_v->sym); } else { printf("nil"); } printf(")"); break; } }