lccrt/lib/irv/lccrt_metadata.c

1092 lines
31 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Part of the Lccrt Project, under the Apache License v2.0
* See http://www.apache.org/licenses/LICENSE-2.0.txt for license information.
* SPDX-License-Identifier: Apache-2.0
*
* lccrt_metadata.c - реализация пользовательского интерфейса метаданных.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include "lccrt_real.h"
/**
* Получить "нулевое" значение для категории.
*/
lccrt_einfo_category_t
lccrt_einfo_category_empty()
{
lccrt_einfo_category_t r = {-1LL};
return (r);
} /* lccrt_einfo_category_empty */
/**
* Проверка категории метаданных на инициализированность.
*/
int
lccrt_einfo_category_is_valued( lccrt_einfo_category_t ecat)
{
int r = (ecat.id >= 0);
return (r);
} /* lccrt_einfo_category_is_valued */
/**
* Преобразовать внешний дескриптор во внутреннюю реализацию.
*/
lccrt_einfo_handle_t
lccrt_einfo_get_handle( lccrt_einfo_reference_t eref)
{
lccrt_einfo_handle_t r;
r.type = eref.data[0];
r.data.i64 = eref.data[1];
return (r);
} /* lccrt_einfo_get_handle */
/**
* Преобразовать внешний дескриптор во внутреннюю реализацию.
*/
lccrt_einfo_reference_t
lccrt_einfo_get_reference( lccrt_einfo_handle_t ehdl)
{
lccrt_einfo_reference_t r;
r.data[0] = ehdl.type;
r.data[1] = ehdl.data.i64;
return (r);
} /* lccrt_einfo_get_reference */
/**
* Преобразовать внешний дескриптор во внутреннюю реализацию.
*/
lccrt_einfo_reference_t
lccrt_einfo_get_block_reference( lccrt_einfo_block_ptr eblock)
{
lccrt_einfo_reference_t r;
lccrt_einfo_handle_t ehdl;
lccrt_check_type_assert( eblock, lccrt_einfo_block_t);
ehdl.type = eblock->type;
ehdl.data.ref = eblock;
r = lccrt_einfo_get_reference( ehdl);
return (r);
} /* lccrt_einfo_get_block_reference */
/**
* Проверяем возможность передачи значения в назначение указанного типа.
*/
int
lccrt_einfo_is_value_assignable( lccrt_einfo_tydescr_ptr etyde, lccrt_einfo_reference_t value)
{
int i;
int r = 0;
lccrt_einfo_handle_t ehdl = lccrt_einfo_get_handle( value);
lccrt_einfo_block_ptr eblock = ehdl.data.ref;
lccrt_check_type_assert( etyde, lccrt_einfo_tydescr_t);
if ( (ehdl.type == LCCRT_EINFO_NULL) )
{
r = 1;
} else if ( (ehdl.type == LCCRT_EINFO_INT64) )
{
if ( (etyde->type == LCCRT_EINFO_INT64) )
{
r = 1;
} else if ( (etyde->type == LCCRT_EINFO_UNION) )
{
for ( i = 0; i < etyde->num_flds; ++i )
{
if ( (etyde->types[i]->type == LCCRT_EINFO_INT64) )
{
r = 1;
break;
}
}
}
} else if ( (etyde->type == LCCRT_EINFO_UNION) )
{
for ( i = 0; i < etyde->num_flds; ++i )
{
lccrt_einfo_tydescr_ptr etydei = etyde->types[i];
if ( (etydei->type == eblock->type)
&& (etydei == eblock->tydescr) )
{
r = 1;
break;
}
}
} else
{
if ( (etyde->type == eblock->type)
&& (etyde == eblock->tydescr) )
{
r = 1;
}
}
return (r);
} /* lccrt_einfo_is_value_assignable */
/**
* Освободить выделенные данные.
*/
void
lccrt_einfo_tydescr_delete( lccrt_einfo_tydescr_ptr etyde)
{
if ( etyde )
{
int i;
lccrt_ctx_ptr ctx = lccrt_module_get_context( etyde->m);
lccrt_check_type_assert( etyde, lccrt_einfo_tydescr_t);
if ( etyde->flds )
{
for ( i = 0; i < etyde->num_flds; ++i ) lccrt_ctx_free( ctx, etyde->flds[i]);
}
lccrt_ctx_free( ctx, etyde->self_name);
lccrt_ctx_free( ctx, etyde->flds);
lccrt_ctx_free( ctx, etyde->types);
lccrt_check_type_done( etyde, lccrt_einfo_tydescr_t);
lccrt_ctx_free( ctx, etyde);
}
return;
} /* lccrt_einfo_tydescr_delete */
/**
* Проверить описание типа данных на принадлежность к LCCRT_EINFO_INT64.
*/
int
lccrt_einfo_is_tydescr_i64( lccrt_einfo_tydescr_ptr etyde)
{
int r = (etyde->type == LCCRT_EINFO_INT64);
return (r);
} /* lccrt_einfo_is_tydescr_i64 */
/**
* Проверить описание типа данных на принадлежность к LCCRT_EINFO_RAW.
*/
int
lccrt_einfo_is_tydescr_raw( lccrt_einfo_tydescr_ptr etyde)
{
int r = (etyde->type == LCCRT_EINFO_RAW);
return (r);
} /* lccrt_einfo_is_tydescr_raw */
/**
* Получить значение поля в описании типа метаданных.
*/
lccrt_einfo_tydescr_ptr
lccrt_einfo_tydescr_get_elem( lccrt_einfo_tydescr_ptr etyde, int elem_k)
{
lccrt_einfo_tydescr_ptr r = 0;
lccrt_check_type_assert( etyde, lccrt_einfo_tydescr_t);
lccrt_assert( (0 <= elem_k) && (elem_k < etyde->num_flds));
r = etyde->types[elem_k];
return (r);
} /* lccrt_einfo_tydescr_get_elem */
/**
* Создать описание типа данных LCCRT_EINFO_INT64.
*/
lccrt_einfo_tydescr_ptr
lccrt_einfo_make_tydescr_i64( lccrt_m_ptr m)
{
lccrt_einfo_tydescr_ptr r = m->einfo_tyi64;
lccrt_ctx_ptr ctx = lccrt_module_get_context( m);
lccrt_check_type_assert( m, lccrt_module_t);
if ( !r )
{
r = lccrt_ctx_malloc( ctx, lccrt_einfo_tydescr_t);
m->einfo_tyi64 = r;
r->next = m->etydescrs_head;
m->etydescrs_head = r;
memset( r, 0, sizeof( r[0]));
lccrt_check_type_init( r, lccrt_einfo_tydescr_t);
r->type = LCCRT_EINFO_INT64;
r->m = m;
}
return (r);
} /* lccrt_einfo_make_tydescr_i64 */
/**
* Создать описание типа данных LCCRT_EINFO_RAW.
*/
lccrt_einfo_tydescr_ptr
lccrt_einfo_make_tydescr_raw( lccrt_m_ptr m)
{
lccrt_einfo_tydescr_ptr r = m->einfo_tyraw;
lccrt_ctx_ptr ctx = lccrt_module_get_context( m);
lccrt_check_type_assert( m, lccrt_module_t);
if ( !r )
{
r = lccrt_ctx_malloc( ctx, lccrt_einfo_tydescr_t);
m->einfo_tyraw = r;
r->next = m->etydescrs_head;
m->etydescrs_head = r;
memset( r, 0, sizeof( r[0]));
lccrt_check_type_init( r, lccrt_einfo_tydescr_t);
r->type = LCCRT_EINFO_RAW;
r->m = m;
}
return (r);
} /* lccrt_einfo_make_tydescr_raw */
/**
* Создать описание типа данных LCCRT_EINFO_ARRAY.
*/
lccrt_einfo_tydescr_ptr
lccrt_einfo_make_tydescr_array( lccrt_m_ptr m, lccrt_einfo_tydescr_ptr etyde)
{
int is_new;
lccrt_einfo_tydescr_ptr r = 0;
lccrt_ctx_ptr ctx = lccrt_module_get_context( m);
lccrt_he_ptr he = lccrt_hash_push( m->einfo_tyarrs, (intptr_t)etyde, &is_new);
lccrt_assert( etyde);
lccrt_check_type_assert( m, lccrt_module_t);
lccrt_check_type_assert( etyde, lccrt_einfo_tydescr_t);
if ( is_new )
{
r = lccrt_ctx_malloc( ctx, lccrt_einfo_tydescr_t);
lccrt_hash_set( he, (intptr_t)r);
memset( r, 0, sizeof( r[0]));
r->next = m->etydescrs_head;
m->etydescrs_head = r;
lccrt_check_type_init( r, lccrt_einfo_tydescr_t);
r->type = LCCRT_EINFO_ARRAY;
r->num_flds = 1;
r->m = m;
r->types = lccrt_ctx_mallocn( ctx, lccrt_einfo_tydescr_ptr, 1);
r->types[0] = etyde;
} else
{
r = (lccrt_einfo_tydescr_ptr)lccrt_hash_get( he);
}
return (r);
} /* lccrt_einfo_make_tydescr_array */
/**
* Создать описание типа данных LCCRT_EINFO_UNION.
*/
lccrt_einfo_tydescr_ptr
lccrt_einfo_make_tydescr_union( lccrt_m_ptr m, int num_flds, lccrt_eitd_ptr *flds_types)
{
int i;
lccrt_einfo_tydescr_ptr r = 0;
lccrt_ctx_ptr ctx = lccrt_module_get_context( m);
lccrt_assert( num_flds >= 0);
r = lccrt_ctx_malloc( ctx, lccrt_einfo_tydescr_t);
memset( r, 0, sizeof( r[0]));
r->next = m->etydescrs_head;
m->etydescrs_head = r;
lccrt_check_type_init( r, lccrt_einfo_tydescr_t);
r->type = LCCRT_EINFO_UNION;
r->num_flds = num_flds;
r->m = m;
r->flds = lccrt_ctx_mallocn( ctx, char *, num_flds);
r->types = lccrt_ctx_mallocn( ctx, lccrt_einfo_tydescr_ptr, num_flds);
for ( i = 0; i < num_flds; ++i )
{
r->types[i] = flds_types[i];
lccrt_assert( flds_types[i]->type != LCCRT_EINFO_UNION);
}
return (r);
} /* lccrt_einfo_make_tydescr_union */
/**
* Создать описание типа данных LCCRT_EINFO_STRUCT.
*/
lccrt_einfo_tydescr_ptr
lccrt_einfo_make_tydescr_struct( lccrt_m_ptr m, const char *name, int num_flds,
const char **flds_names, lccrt_eitd_ptr *flds_types)
{
int i;
int is_new;
lccrt_einfo_tydescr_ptr r = 0;
lccrt_ctx_ptr ctx = lccrt_module_get_context( m);
lccrt_he_ptr he = lccrt_hash_push( m->einfo_tysts, (intptr_t)name, &is_new);
lccrt_check_type_assert( m, lccrt_module_t);
lccrt_assert( num_flds >= 0);
if ( is_new )
{
r = lccrt_ctx_malloc( ctx, lccrt_einfo_tydescr_t);
lccrt_hash_set( he, (intptr_t)r);
memset( r, 0, sizeof( r[0]));
r->next = m->etydescrs_head;
m->etydescrs_head = r;
lccrt_check_type_init( r, lccrt_einfo_tydescr_t);
r->type = LCCRT_EINFO_STRUCT;
r->num_flds = num_flds;
r->m = m;
r->self_name = lccrt_ctx_copy_str( ctx, name);
r->flds = lccrt_ctx_mallocn( ctx, char *, num_flds);
r->types = lccrt_ctx_mallocn( ctx, lccrt_einfo_tydescr_ptr, num_flds);
for ( i = 0; i < num_flds; ++i )
{
r->types[i] = flds_types[i];
r->flds[i] = lccrt_ctx_copy_str( ctx, flds_names[i]);
}
} else
{
int is_err = 0;
r = (lccrt_einfo_tydescr_ptr)lccrt_hash_get( he);
if ( (strcmp( r->self_name, name) != 0)
|| (r->num_flds != num_flds) )
{
is_err = 1;
}
for ( i = 0; i < num_flds; ++i )
{
if ( (r->types[i] != flds_types[i])
|| (strcmp( r->flds[i], flds_names[i]) != 0) )
{
is_err = 1;
break;
}
}
if ( is_err )
{
r = 0;
lccrt_ctx_error( ctx, 0, "type description of struct '%s' differs from the early one", name);
}
}
return (r);
} /* lccrt_einfo_make_tydescr_struct */
/**
* Поиск в описании структурного типа дескриптора поля.
*/
lccrt_einfo_field_id_t
lccrt_einfo_find_tydescr_field( lccrt_einfo_tydescr_ptr etyde, const char *name)
{
int i;
lccrt_einfo_field_id_t r = {{0, 0}};
lccrt_check_type_assert( etyde, lccrt_einfo_tydescr_t);
lccrt_assert( etyde->type == LCCRT_EINFO_STRUCT);
for ( i = 0; i < etyde->num_flds; ++i )
{
if ( (strcmp( name, etyde->flds[i]) == 0) )
{
r.data[0] = (intptr_t)etyde;
r.data[1] = i;
break;
}
}
return (r);
} /* lccrt_einfo_find_tydescr_field */
/**
* Создать в рамках модуля новую категорию метаданных.
*/
lccrt_einfo_category_t
lccrt_module_new_einfo_category( lccrt_module_ptr m, const char *name)
{
lccrt_einfo_category_t r;
int is_new = 0;
lccrt_he_ptr he = lccrt_hash_push( m->einfo_cats, (intptr_t)name, &is_new);
lccrt_assert( is_new);
lccrt_hash_set( he, (intptr_t)m->einfo_ident);
r.id = m->einfo_ident;
m->einfo_ident++;
return (r);
} /* lccrt_module_new_einfo_category */
/**
* Поиск в модуле категорию метаданных по имени.
*/
lccrt_einfo_category_t
lccrt_module_find_einfo_category( lccrt_module_ptr m, const char *name)
{
lccrt_einfo_category_t r = {-1LL};
lccrt_hash_entry_ptr he = lccrt_hash_find( m->einfo_cats, (intptr_t)name);
if ( he )
{
r.id = lccrt_hash_get( he);
}
return (r);
} /* lccrt_module_find_einfo_category */
/**
* Проверка метаданных на наличие значения.
*/
int
lccrt_einfo_is_valued( lccrt_einfo_reference_t eref)
{
int r = 0;
lccrt_einfo_handle_t ehdl = lccrt_einfo_get_handle( eref);
if ( (ehdl.type == LCCRT_EINFO_INT64)
|| (ehdl.type == LCCRT_EINFO_RAW)
|| (ehdl.type == LCCRT_EINFO_ARRAY)
|| (ehdl.type == LCCRT_EINFO_UNION)
|| (ehdl.type == LCCRT_EINFO_STRUCT) )
{
r = 1;
}
return (r);
} /* lccrt_einfo_is_valued */
/**
* Получить количество элементов в метаданных.
*/
int
lccrt_einfo_get_num_args( lccrt_einfo_reference_t eref)
{
int r = 0;
lccrt_einfo_handle_t ehdl = lccrt_einfo_get_handle( eref);
if ( (ehdl.type == LCCRT_EINFO_ARRAY)
|| (ehdl.type == LCCRT_EINFO_STRUCT)
|| (ehdl.type == LCCRT_EINFO_RAW) )
{
lccrt_einfo_block_ptr eblock = ehdl.data.ref;
lccrt_check_type_assert( eblock, lccrt_einfo_block_t);
r = eblock->num_args;
}
return (r);
} /* lccrt_einfo_get_num_args */
/**
* Получить элемент массива.
*/
lccrt_einfo_reference_t
lccrt_einfo_get_elem( lccrt_einfo_reference_t eref, int elem_k)
{
lccrt_einfo_reference_t r = {0};
lccrt_einfo_handle_t ehdl = lccrt_einfo_get_handle( eref);
lccrt_einfo_block_ptr eblock = ehdl.data.ref;
lccrt_assert( ehdl.type == LCCRT_EINFO_ARRAY);
lccrt_check_type_assert( eblock, lccrt_einfo_block_t);
lccrt_assert( (0 <= elem_k) && (elem_k < eblock->num_args));
r = lccrt_einfo_get_reference( eblock->data.elems[elem_k]);
return (r);
} /* lccrt_einfo_get_elem */
/**
* Получить поле структуры.
*/
lccrt_einfo_reference_t
lccrt_einfo_get_field( lccrt_einfo_reference_t eref, lccrt_eifi_t eifi)
{
lccrt_einfo_reference_t r = {0};
lccrt_einfo_handle_t ehdl = lccrt_einfo_get_handle( eref);
lccrt_einfo_block_ptr eblock = ehdl.data.ref;
lccrt_assert( ehdl.type == LCCRT_EINFO_STRUCT);
lccrt_check_type_assert( eblock, lccrt_einfo_block_t);
lccrt_assert( (intptr_t)eblock->tydescr == eifi.data[0]);
lccrt_assert( (0 <= eifi.data[1]) && (eifi.data[1] < eblock->num_args));
r = lccrt_einfo_get_reference( eblock->data.flds[eifi.data[1]]);
return (r);
} /* lccrt_einfo_get_field */
/**
* Получить значение байтового массива.
*/
uint8_t *
lccrt_einfo_get_raw_data( lccrt_einfo_reference_t eref)
{
uint8_t *r = 0;
lccrt_einfo_handle_t ehdl = lccrt_einfo_get_handle( eref);
lccrt_einfo_block_ptr eblock = ehdl.data.ref;
lccrt_assert( ehdl.type == LCCRT_EINFO_RAW);
lccrt_check_type_assert( eblock, lccrt_einfo_block_t);
r = eblock->data.rdata;
return (r);
} /* lccrt_einfo_get_raw_data */
/**
* Получить для нескалярных метаданных ссылки на описание типа данных.
*/
lccrt_einfo_tydescr_ptr
lccrt_einfo_get_tydescr( lccrt_einfo_reference_t eref)
{
lccrt_einfo_tydescr_ptr r = 0;
lccrt_einfo_handle_t ehdl = lccrt_einfo_get_handle( eref);
if ( (ehdl.type == LCCRT_EINFO_ARRAY)
|| (ehdl.type == LCCRT_EINFO_STRUCT)
|| (ehdl.type == LCCRT_EINFO_RAW) )
{
r = ehdl.data.ref->tydescr;
}
return (r);
} /* lccrt_einfo_get_tydescr */
/**
* Проверка типа метаданных на передачу по значению.
*/
int
lccrt_einfo_is_scalar( lccrt_einfo_reference_t eref)
{
int r = 0;
lccrt_einfo_handle_t ehdl = lccrt_einfo_get_handle( eref);
if ( (ehdl.type == LCCRT_EINFO_INT64) )
{
r = 1;
}
return (r);
} /* lccrt_einfo_is_scalar */
/**
* Удалить данные структуры и саму структуру.
*/
void
lccrt_einfo_block_delete( lccrt_einfo_block_ptr eblock)
{
if ( eblock )
{
lccrt_ctx_ptr ctx = lccrt_module_get_context( eblock->tydescr->m);
lccrt_check_type_assert( eblock, lccrt_einfo_block_t);
lccrt_check_type_assert( eblock->tydescr, lccrt_einfo_tydescr_t);
lccrt_ctx_free( ctx, eblock->data.flds);
lccrt_check_type_done( eblock, lccrt_einfo_block_t);
lccrt_ctx_free( ctx, eblock);
}
return;
} /* lccrt_einfo_block_delete */
/**
* Проверить дескриптор на равенство нулевому дескриптору.
*/
int
lccrt_einfo_is_empty( lccrt_einfo_reference_t eref)
{
int r = ((eref.data[0] == 0) && (eref.data[1] == 0));
lccrt_assert( r != lccrt_einfo_is_valued( eref));
return (r);
} /* lccrt_einfo_is_empty */
/**
* Создать нулевой дескриптор.
*/
lccrt_einfo_reference_t
lccrt_einfo_new_empty()
{
lccrt_einfo_reference_t r;
lccrt_einfo_handle_t ehdl;
ehdl.type = LCCRT_EINFO_NULL;
ehdl.data.i64 = 0;
r = lccrt_einfo_get_reference( ehdl);
return (r);
} /* lccrt_einfo_new_empty */
/**
* Создать дескриптор целочисленных данных.
*/
lccrt_einfo_reference_t
lccrt_einfo_new_i64( uint64_t value)
{
lccrt_einfo_reference_t r;
lccrt_einfo_handle_t ehdl;
ehdl.type = LCCRT_EINFO_INT64;
ehdl.data.i64 = value;
r = lccrt_einfo_get_reference( ehdl);
return (r);
} /* lccrt_einfo_new_i64 */
/**
* Создать дескриптор байтового массива.
*/
lccrt_einfo_reference_t
lccrt_einfo_new_raw( lccrt_module_ptr m, int length, const uint8_t *data)
{
lccrt_einfo_reference_t r;
lccrt_einfo_handle_t ehdl;
lccrt_einfo_block_ptr eblock;
lccrt_ctx_ptr ctx = lccrt_module_get_context( m);
eblock = lccrt_ctx_malloc( ctx, lccrt_einfo_block_t);
memset( eblock, 0, sizeof( eblock[0]));
lccrt_check_type_init( eblock, lccrt_einfo_block_t);
eblock->next = m->eblocks_head;
m->eblocks_head = eblock;
eblock->type = LCCRT_EINFO_RAW;
eblock->tydescr = lccrt_einfo_make_tydescr_raw( m);
eblock->num_args = length;
eblock->data.rdata = lccrt_ctx_mallocn( ctx, uint8_t, length);
memcpy( eblock->data.rdata, data, length);
ehdl.type = LCCRT_EINFO_RAW;
ehdl.data.ref = eblock;
r = lccrt_einfo_get_reference( ehdl);
return (r);
} /* lccrt_einfo_new_raw */
/**
* Создать дескриптор байтового массива на основе строке.
*/
lccrt_einfo_reference_t
lccrt_einfo_new_raw_by_string( lccrt_module_ptr m, const char *data)
{
lccrt_einfo_reference_t r = lccrt_einfo_new_raw( m, strlen( data) + 1, data);
return (r);
} /* lccrt_einfo_new_raw_by_string */
/**
* Создать значение типа массив.
*/
lccrt_einfo_reference_t
lccrt_einfo_new_array( lccrt_einfo_tydescr_ptr etyde, int alloc_elems)
{
lccrt_einfo_reference_t r;
lccrt_einfo_handle_t ehdl;
lccrt_einfo_block_ptr eblock;
lccrt_module_ptr m = etyde->m;
lccrt_ctx_ptr ctx = lccrt_module_get_context( m);
lccrt_assert( alloc_elems >= 0);
lccrt_check_type_assert( etyde, lccrt_einfo_tydescr_t);
eblock = lccrt_ctx_malloc( ctx, lccrt_einfo_block_t);
memset( eblock, 0, sizeof( eblock[0]));
lccrt_check_type_init( eblock, lccrt_einfo_block_t);
eblock->next = m->eblocks_head;
m->eblocks_head = eblock;
eblock->type = LCCRT_EINFO_ARRAY;
eblock->tydescr = etyde;
//eblock->max_args = (alloc_elems == 0) ? 4 : alloc_elems;
eblock->num_args = alloc_elems;
eblock->max_args = alloc_elems;
eblock->data.elems = lccrt_ctx_mallocn( ctx, lccrt_einfo_handle_t, eblock->max_args);
memset( eblock->data.flds, 0, eblock->max_args*sizeof( eblock->data.elems[0]));
ehdl.type = LCCRT_EINFO_ARRAY;
ehdl.data.ref = eblock;
r = lccrt_einfo_get_reference( ehdl);
return (r);
} /* lccrt_einfo_new_array */
/**
* Создать значение типа структура.
*/
lccrt_einfo_reference_t
lccrt_einfo_new_struct( lccrt_einfo_tydescr_ptr etyde)
{
lccrt_einfo_reference_t r;
lccrt_einfo_handle_t ehdl;
lccrt_einfo_block_ptr eblock;
lccrt_module_ptr m = etyde->m;
lccrt_ctx_ptr ctx = lccrt_module_get_context( m);
lccrt_check_type_assert( etyde, lccrt_einfo_tydescr_t);
lccrt_assert( etyde->type == LCCRT_EINFO_STRUCT);
eblock = lccrt_ctx_malloc( ctx, lccrt_einfo_block_t);
memset( eblock, 0, sizeof( eblock[0]));
lccrt_check_type_init( eblock, lccrt_einfo_block_t);
eblock->next = m->eblocks_head;
m->eblocks_head = eblock;
eblock->type = LCCRT_EINFO_STRUCT;
eblock->tydescr = etyde;
eblock->num_args = etyde->num_flds;
eblock->data.flds = lccrt_ctx_mallocn( ctx, lccrt_einfo_handle_t, eblock->num_args);
memset( eblock->data.flds, 0, eblock->num_args*sizeof( eblock->data.flds[0]));
ehdl.type = LCCRT_EINFO_STRUCT;
ehdl.data.ref = eblock;
r = lccrt_einfo_get_reference( ehdl);
return (r);
} /* lccrt_einfo_new_struct */
/**
* Установить значение элемента в массиве.
*/
void
lccrt_einfo_set_elem( lccrt_eir_t eref, int index, lccrt_eir_t value)
{
lccrt_einfo_handle_t ehdl = lccrt_einfo_get_handle( eref);
lccrt_einfo_block_ptr eblock = ehdl.data.ref;
lccrt_assert( (0 <= index) && (index < eblock->num_args));
lccrt_assert( ehdl.type == LCCRT_EINFO_ARRAY);
lccrt_assert( lccrt_einfo_is_value_assignable( eblock->tydescr->types[0], value));
eblock->data.elems[index] = lccrt_einfo_get_handle( value);
#if 0
lccrt_einfo_handle_t ehdl = lccrt_einfo_get_handle( eref);
lccrt_einfo_block_ptr eblock = ehdl.data.ref;
elem_ident = (elem_ident < 0) ? eblock->num_args : elem_ident;
#endif
return;
} /* lccrt_einfo_set_elem */
/**
* Добавить значение в массив, увеличив его длину по необходимости.
*/
void
lccrt_einfo_push_elem( lccrt_eir_t eref, lccrt_eir_t value)
{
lccrt_einfo_handle_t ehdl = lccrt_einfo_get_handle( eref);
lccrt_einfo_block_ptr eblock = ehdl.data.ref;
int num_args = eblock->num_args;
lccrt_ctx_ptr ctx = lccrt_module_get_context( eblock->tydescr->m);
lccrt_check_type_assert( eblock, lccrt_einfo_block_t);
lccrt_assert( eblock->type == LCCRT_EINFO_ARRAY);
lccrt_assert( (0 <= num_args) && (num_args <= eblock->max_args));
lccrt_assert( lccrt_einfo_is_value_assignable( eblock->tydescr->types[0], value));
if ( (num_args == eblock->max_args) )
{
lccrt_einfo_handle_t *new_data = 0;
if ( (eblock->max_args == 0) )
{
eblock->max_args = 4;
} else
{
eblock->max_args = 2*eblock->max_args;
}
new_data = lccrt_ctx_mallocn( ctx, lccrt_einfo_handle_t, eblock->max_args);
memcpy( new_data, eblock->data.elems, num_args*sizeof( new_data[0]));
memset( new_data + num_args, 0, (eblock->max_args - num_args)*sizeof( new_data[0]));
lccrt_ctx_free( ctx, eblock->data.elems);
eblock->data.elems = new_data;
}
eblock->data.elems[num_args] = lccrt_einfo_get_handle( value);
eblock->num_args++;
return;
} /* lccrt_einfo_push_elem */
/**
* Установить значение поля структуры.
*/
void
lccrt_einfo_set_field( lccrt_eir_t eref, lccrt_eifi_t eifi, lccrt_eir_t value)
{
int index = eifi.data[1];
lccrt_einfo_tydescr_ptr etyde = (lccrt_einfo_tydescr_ptr)eifi.data[0];
lccrt_einfo_handle_t ehdl = lccrt_einfo_get_handle( eref);
lccrt_einfo_handle_t ehdl_value = lccrt_einfo_get_handle( value);
lccrt_einfo_block_ptr eblock = ehdl.data.ref;
lccrt_assert( eblock->tydescr == etyde);
lccrt_assert( (ehdl.type == LCCRT_EINFO_STRUCT) && (eblock->type == LCCRT_EINFO_STRUCT));
lccrt_assert( (0 <= eifi.data[1]) && (eifi.data[1] < eblock->num_args));
lccrt_check_type_assert( eblock, lccrt_einfo_block_t);
lccrt_assert( lccrt_einfo_is_value_assignable( eblock->tydescr->types[index], value));
eblock->data.flds[index] = ehdl_value;
return;
} /* lccrt_einfo_set_field */
/**
* Получить значение метаданных из цепочки привязки.
*/
lccrt_einfo_reference_t
lccrt_einfo_link_get_value( lccrt_einfo_link_ptr elink)
{
lccrt_einfo_reference_t r;
if ( elink )
{
r = lccrt_einfo_get_reference( elink->value);
} else
{
lccrt_einfo_handle_t ehdl = {LCCRT_EINFO_NULL};
r = lccrt_einfo_get_reference( ehdl);
}
return (r);
} /* lccrt_einfo_link_get_value */
/**
* Создать звено для цепочки привязки мета-данные.
*/
lccrt_einfo_link_ptr
lccrt_einfo_link_new( lccrt_m_ptr m, lccrt_eil_ptr elink0, lccrt_eic_t ecat, lccrt_eir_t value)
{
lccrt_einfo_link_ptr elink = 0;
lccrt_ctx_ptr ctx = lccrt_module_get_context( m);
elink = lccrt_ctx_malloc( ctx, lccrt_einfo_link_t);
memset( elink, 0, sizeof( elink[0]));
lccrt_check_type_init( elink, lccrt_einfo_link_t);
elink->next = elink0;
elink->ident = ecat;
elink->value = lccrt_einfo_get_handle( value);
return (elink);
} /* lccrt_einfo_link_new */
/**
* Поиск звена в цепочке привязки мета-данные по категории.
*/
lccrt_einfo_link_ptr
lccrt_einfo_link_find( lccrt_eil_ptr elink, lccrt_eic_t ecat)
{
while ( elink
&& (elink->ident.id != ecat.id) )
{
elink = elink->next;
}
return (elink);
} /* lccrt_einfo_link_find */
/**
* Добавить в цепочку привязки новые мета-данные, либо изменить значение старых.
*/
lccrt_einfo_link_ptr
lccrt_einfo_link_push_value( lccrt_m_ptr m, lccrt_eil_ptr elink0, lccrt_eic_t ecat, lccrt_eir_t value)
{
lccrt_einfo_link_ptr elink = lccrt_einfo_link_find( elink0, ecat);
if ( elink )
{
/* Мета-данные с таким именем уже существуют. */
elink->value = lccrt_einfo_get_handle( value);
} else
{
elink0 = lccrt_einfo_link_new( m, elink0, ecat, value);
}
return (elink0);
} /* lccrt_einfo_link_push_value */
/**
* Удалить звено цепочки привязки einfo-данных.
*/
void
lccrt_einfo_link_delete( lccrt_einfo_link_ptr elink)
{
if ( elink )
{
lccrt_einfo_block_ptr eblock = elink->value.data.ref;
lccrt_check_type_assert( elink, lccrt_einfo_link_t);
lccrt_check_type_assert( eblock, lccrt_einfo_block_t);
lccrt_check_type_assert( eblock->tydescr, lccrt_einfo_tydescr_t);
lccrt_check_type_done( elink, lccrt_einfo_link_t);
lccrt_ctx_free( lccrt_module_get_context( eblock->tydescr->m), elink);
}
return;
} /* lccrt_einfo_link_delete */
/**
* Удалить цепочку привязки einfo-данных.
*/
lccrt_einfo_link_ptr
lccrt_einfo_link_delete_chain( lccrt_einfo_link_ptr elink)
{
while ( elink )
{
lccrt_einfo_link_ptr next = elink->next;
lccrt_einfo_link_delete( elink);
elink = next;
}
return (0);
} /* lccrt_einfo_link_delete_chain */
/**
* Пронумеровать описание типов einfo-данных с помощью указанной хеш-таблицы.
*/
static uint64_t
lccrt_einfo_tydescr_number( uint64_t ident, lccrt_einfo_tydescr_ptr etyde, lccrt_hash_ptr tbl)
{
lccrt_hash_entry_ptr he;
int is_new = 0;
lccrt_ctx_ptr ctx = lccrt_module_get_context( etyde->m);
lccrt_check_type_assert( etyde, lccrt_einfo_tydescr_t);
he = lccrt_hash_push( tbl, (intptr_t)etyde, &is_new);
if ( !is_new )
{
intptr_t cur_ident = lccrt_hash_get( he);
if ( (cur_ident < 0) )
{
lccrt_ctx_error( ctx, 0, "Recursive loop in extended information types descriptions");
}
} else
{
int64_t i;
lccrt_hash_set( he, (uintptr_t)(-1LL));
for ( i = 0; i < etyde->num_flds; ++i )
{
ident = lccrt_einfo_tydescr_number( ident, etyde->types[i], tbl);
}
he = lccrt_hash_find( tbl, (intptr_t)etyde);
lccrt_hash_set( he, (uintptr_t)ident);
++ident;
}
return (ident);
} /* lccrt_einfo_tydescr_number */
/**
* Пронумеровать поддерево метаданных с помощью указнной хеш-таблицы.
*/
static uint64_t
lccrt_einfo_block_number( uint64_t ident, lccrt_einfo_block_ptr eblock, lccrt_hash_ptr tbl)
{
lccrt_hash_entry_ptr he;
int is_new = 0;
lccrt_ctx_ptr ctx = lccrt_module_get_context( eblock->tydescr->m);
lccrt_check_type_assert( eblock, lccrt_einfo_block_t);
he = lccrt_hash_push( tbl, (intptr_t)eblock, &is_new);
if ( !is_new )
{
intptr_t cur_ident = lccrt_hash_get( he);
if ( (cur_ident < 0) )
{
lccrt_ctx_error( ctx, 0, "Recursive loop in extended information");
}
} else
{
int64_t i;
lccrt_hash_set( he, (uintptr_t)(-1LL));
if ( (eblock->type == LCCRT_EINFO_STRUCT)
|| (eblock->type == LCCRT_EINFO_UNION) )
{
for ( i = eblock->num_args - 1; i >= 0; --i )
{
lccrt_einfo_handle_t q = eblock->data.flds[i];
if ( (q.type == LCCRT_EINFO_STRUCT)
|| (q.type == LCCRT_EINFO_UNION)
|| (q.type == LCCRT_EINFO_ARRAY)
|| (q.type == LCCRT_EINFO_RAW) )
{
ident = lccrt_einfo_block_number( ident, q.data.ref, tbl);
}
}
} else if ( (eblock->type == LCCRT_EINFO_ARRAY) )
{
for ( i = eblock->num_args - 1; i >= 0; --i )
{
lccrt_einfo_handle_t q = eblock->data.elems[i];
if ( (q.type == LCCRT_EINFO_STRUCT)
|| (q.type == LCCRT_EINFO_UNION)
|| (q.type == LCCRT_EINFO_ARRAY)
|| (q.type == LCCRT_EINFO_RAW) )
{
ident = lccrt_einfo_block_number( ident, q.data.ref, tbl);
}
}
} else if ( (eblock->type == LCCRT_EINFO_RAW) )
{
} else
{
lccrt_assert( 0);
}
he = lccrt_hash_find( tbl, (intptr_t)eblock);
lccrt_hash_set( he, (uintptr_t)ident);
++ident;
}
return (ident);
} /* lccrt_einfo_block_number */
/**
* Для каждого узла дерева метаданных (STRUCT или ARRAY) провести нумерацию
* с помощью хеширования в указанной хеш-таблице.
*/
void
lccrt_module_einfo_number( lccrt_module_ptr m, lccrt_hash_ptr btbl, lccrt_hash_ptr ttbl)
{
lccrt_check_type_assert( m, lccrt_module_t);
// Нумеруем блоки.
if ( btbl )
{
lccrt_einfo_block_ptr unit;
uint64_t ident = 0;
for ( unit = m->eblocks_head; unit; unit = unit->next )
{
ident = lccrt_einfo_block_number( ident, unit, btbl);
}
}
// Нумеруем описания типов.
if ( ttbl )
{
lccrt_einfo_tydescr_ptr unit;
uint64_t ident = 0;
for ( unit = m->etydescrs_head; unit; unit = unit->next )
{
ident = lccrt_einfo_tydescr_number( ident, unit, ttbl);
}
}
return;
} /* lccrt_module_einfo_number */