HelenOS sources

root/uspace/app/sbi/src/rdata.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rdata_item_new
  2. rdata_addr_var_new
  3. rdata_aprop_named_new
  4. rdata_aprop_indexed_new
  5. rdata_addr_prop_new
  6. rdata_address_new
  7. rdata_value_new
  8. rdata_var_new
  9. rdata_ref_new
  10. rdata_deleg_new
  11. rdata_enum_new
  12. rdata_array_new
  13. rdata_object_new
  14. rdata_bool_new
  15. rdata_char_new
  16. rdata_int_new
  17. rdata_string_new
  18. rdata_resource_new
  19. rdata_symbol_new
  20. rdata_array_alloc_element
  21. rdata_array_get_dim
  22. rdata_item_delete
  23. rdata_addr_var_delete
  24. rdata_addr_prop_delete
  25. rdata_aprop_named_delete
  26. rdata_aprop_indexed_delete
  27. rdata_address_delete
  28. rdata_value_delete
  29. rdata_var_delete
  30. rdata_bool_delete
  31. rdata_char_delete
  32. rdata_int_delete
  33. rdata_string_delete
  34. rdata_ref_delete
  35. rdata_deleg_delete
  36. rdata_enum_delete
  37. rdata_array_delete
  38. rdata_object_delete
  39. rdata_resource_delete
  40. rdata_symbol_delete
  41. rdata_value_copy
  42. rdata_var_copy
  43. rdata_var_copy_to
  44. rdata_bool_copy
  45. rdata_char_copy
  46. rdata_int_copy
  47. rdata_string_copy
  48. rdata_ref_copy
  49. rdata_deleg_copy
  50. rdata_enum_copy
  51. rdata_array_copy
  52. rdata_object_copy
  53. rdata_resource_copy
  54. rdata_symbol_copy
  55. rdata_var_destroy
  56. rdata_var_destroy_inner
  57. rdata_item_destroy
  58. rdata_address_destroy
  59. rdata_addr_var_destroy
  60. rdata_addr_prop_destroy
  61. rdata_aprop_named_destroy
  62. rdata_aprop_indexed_destroy
  63. rdata_value_destroy
  64. rdata_bool_destroy
  65. rdata_char_destroy
  66. rdata_int_destroy
  67. rdata_string_destroy
  68. rdata_ref_destroy
  69. rdata_deleg_destroy
  70. rdata_enum_destroy
  71. rdata_array_destroy
  72. rdata_object_destroy
  73. rdata_resource_destroy
  74. rdata_symbol_destroy
  75. rdata_var_read
  76. rdata_var_write
  77. rdata_item_print
  78. rdata_address_print
  79. rdata_value_print
  80. rdata_var_print

/*
 * 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 <stdlib.h>
#include <assert.h>
#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;
        }
}

/* [<][>][^][v][top][bottom][index][help] */
HelenOS homepage, sources at GitHub