/** * 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_ctx.c - реализация пользовательский интерфейс (динамической) компиляции. */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include "lccrt_irv.h" #define LCCRT_CTX_PLUGIN_MAX_NUMBER (256) #define LCCRT_CTX_PLUGIN_TARGET_MAX_NUMBER (256) #define LCCRT_CTX_PLUGIN_NAME_LENGTH (4096 - 1) #define lccrt_ctx_error_plugin_sym( ctx, lname, sname) \ lccrt_ctx_error( ctx, 0, "Plugin library [%s] hasn't symbol [%s]\n", \ lname, sname) lccrt_check_type_define( lccrt_type_t); lccrt_check_type_define( lccrt_varinit_t); lccrt_check_type_define( lccrt_var_t); lccrt_check_type_define( lccrt_oper_t); lccrt_check_type_define( lccrt_oper_iterator_t); lccrt_check_type_define( lccrt_function_t); lccrt_check_type_define( lccrt_function_jit_info_t); lccrt_check_type_define( lccrt_module_t); lccrt_check_type_define( lccrt_einfo_tydescr_t); lccrt_check_type_define( lccrt_einfo_block_t); lccrt_check_type_define( lccrt_einfo_link_t); lccrt_check_type_define( lccrt_context_t); lccrt_check_type_define( lccrt_plugin_t); /** * Данные стандартного менеджера вывода сообщений в файл. */ typedef struct { int8_t is_init; /* флаг инициализации структуры */ FILE *file; /* файл для печати сообщений */ pid_t pid; /* идентификатор родительского процесса */ } lccrt_dir_error_info_t; static void *lccrt_std_alloc( void *pool, uint64_t size); static void *lccrt_std_realloc( void *pool, void *ptr, uint64_t size); static void lccrt_std_free( void *pool, void *ptr); static void lccrt_std_error( void *data, int errid, const char *fmt, ...); static void lccrt_dir_error( void *data, int errid, const char *fmt, ...); static void lccrt_std_warning( void *data, int errid, const char *fmt, ...); static void lccrt_dir_warning( void *data, int errid, const char *fmt, ...); /** * Стандартные менеджеры. */ lccrt_err_t lccrt_std_err = {0, &lccrt_std_error, &lccrt_std_warning}; lccrt_mem_t lccrt_std_mem = {0, &lccrt_std_alloc, &lccrt_std_realloc, &lccrt_std_free}; lccrt_err_t lccrt_dir_err = {0, &lccrt_dir_error, &lccrt_dir_warning}; /** * Стандартный malloc. */ static void * lccrt_std_alloc( void *pool, uint64_t size) { void *result = (void *)malloc( size); return (result); } /* lccrt_std_alloc */ /** * Стандартный realloc. */ static void * lccrt_std_realloc( void *pool, void *ptr, uint64_t size) { void *result = (void *)realloc( ptr, size); return (result); } /* lccrt_std_realloc */ /** * Стандартный free. */ static void lccrt_std_free( void *pool, void *ptr) { free( ptr); return; } /* lccrt_std_free */ /** * Стандартная реакция на ошибку. */ static void lccrt_std_error( void *data, int errid, const char *fmt, ...) { char str[256]; va_list ap; va_start( ap, fmt); vsnprintf( str, 255, fmt, ap); va_end( ap); perror( str); if ( errid ) { exit( errid); } return; } /* lccrt_std_error */ /** * Стандартная реакция на предупреждение. */ static void lccrt_std_warning( void *data, int errid, const char *fmt, ...) { char str[256]; va_list ap; va_start( ap, fmt); vsnprintf( str, 255, fmt, ap); va_end( ap); printf( "%s", str); return; } /* lccrt_std_warning */ /** * Подготовка данных для вывода сообщений. */ static lccrt_dir_error_info_t * lccrt_dir_error_init( void) { static __thread lccrt_dir_error_info_t ei = {0}; if ( !ei.is_init || (ei.pid != getpid()) ) { char s[1024]; const char *dir_name = getenv( "LCCRT_ERRDIR"); ei.is_init = 1; ei.pid = getpid(); if ( !dir_name || (dir_name[0] == 0) ) { dir_name = "."; } snprintf( s, 1024, "mkdir -p -m a+rwx %s", dir_name); system( s); snprintf( s, 1024, "%s/lccrt.errlog.pid_%d.tid_%d.txt", dir_name, getpid(), (unsigned)syscall( SYS_gettid)); ei.file = fopen( s, "w"); } return (&ei); } /* lccrt_dir_error_init */ /** * Стандартная реакция на ошибку. */ static void lccrt_dir_error( void *data, int errid, const char *fmt, ...) { va_list ap; lccrt_dir_error_info_t *ei = lccrt_dir_error_init(); va_start( ap, fmt); vfprintf( ei->file, fmt, ap); va_end( ap); fflush( ei->file); if ( errid ) { exit( errid); } return; } /* lccrt_dir_error */ /** * Стандартная реакция на предупреждение. */ static void lccrt_dir_warning( void *data, int errid, const char *fmt, ...) { va_list ap; lccrt_dir_error_info_t *ei = lccrt_dir_error_init(); va_start( ap, fmt); vfprintf( ei->file, fmt, ap); va_end( ap); fflush( ei->file); return; } /* lccrt_dir_warning */ /** * Чтение из файла строки. */ static void lccrt_getline( FILE *f, int max_str_len, char *line) { int c; int k = 0; c = getc( f); while ( (c != '\n') && (c != EOF) && isspace( c) ) { c = getc( f); } while ( (c != '\n') && (c != EOF) ) { if ( (k < max_str_len) ) { line[k] = c; ++k; } c = getc( f); } line[k] = 0; return; } /* lccrt_getline */ /** * Получить ссылку на метод. */ void * lccrt_ctx_plugin_get_func( lccrt_plg_ptr p, int func_num) { void *r = 0; lccrt_check_type_assert( p, lccrt_plugin_t); if ( (0 <= func_num) && (func_num < p->num_funcs) ) { r = p->funcs[func_num]; } return (r); } /* lccrt_ctx_plugin_get_func */ /** * Закрытие библиотеки с ассемблером. */ static void lccrt_ctx_plugin_unload( lccrt_plugin_t *a) { int k; lccrt_context_ptr ctx = a->ctx; lccrt_check_type_assert( a, lccrt_plugin_t); if ( a->lib ) { dlclose( a->lib); a->lib = 0; } if ( a->targs ) { for ( k = 0; k < a->num_targs; ++k ) { lccrt_ctx_free( ctx, a->targs[k]); lccrt_ctx_free( ctx, a->lccrt_s[k]); lccrt_ctx_free( ctx, a->include_s[k]); } lccrt_ctx_free( ctx, a->targs); lccrt_ctx_free( ctx, a->lccrt_s); lccrt_ctx_free( ctx, a->include_s); a->targs = 0; } lccrt_ctx_free( ctx, a->lib_name); lccrt_ctx_free( ctx, a->lccrt_ver); lccrt_ctx_free( ctx, a->lccrt_s); lccrt_ctx_free( ctx, a->include_s); a->lib_name = 0; a->lccrt_ver = 0; a->lccrt_s = 0; a->include_s = 0; a->num_targs = 0; a->num_funcs = 0; lccrt_ctx_free( ctx, a->funcs); a->funcs = 0; return; } /* lccrt_ctx_plugin_unload */ /** * Открытие библиотеки с ассемблером. */ static int lccrt_ctx_load_plugin_lib( lccrt_plugin_t *a, const char *lib_name) { int k; int r = -1; char *cur_name = 0; lccrt_context_ptr ctx = a->ctx; lccrt_check_type_assert( a, lccrt_plugin_t); if ( a->lib ) { lccrt_ctx_error( ctx, 0, "INTERNAL ERROR\n"); return (r); } if ( (lib_name[0] == '/') ) { cur_name = lccrt_ctx_copy_str( ctx, lib_name); } else { cur_name = lccrt_ctx_cat_strs( ctx, ctx->paths.plugins[a->type], "/"); cur_name = lccrt_ctx_catby_strs( ctx, cur_name, lib_name); } a->lib = dlopen( cur_name, RTLD_LAZY); if ( !a->lib ) { lccrt_ctx_error( ctx, 0, "Can't load plugin library [%s]\n", cur_name); } else { const char **lname; const char **lver; const char *(*targs)[]; int is_asm = (a->type == LCCRT_PLUGIN_TYPE_ASM); a->num_funcs = LCCRT_PLUGIN_ASM_FUNC_LAST; a->funcs = lccrt_ctx_mallocn( ctx, void *, a->num_funcs); if ( is_asm ) { a->funcs[LCCRT_PLUGIN_ASM_FUNC_COMP] = dlsym( a->lib, LCCRT_ASM_SFUNC_COMPILE); a->funcs[LCCRT_PLUGIN_ASM_FUNC_TOOL] = dlsym( a->lib, LCCRT_ASM_SFUNC_GETTOOL); if ( !a->funcs[LCCRT_PLUGIN_ASM_FUNC_COMP] ) { lccrt_ctx_error_plugin_sym( ctx, cur_name, LCCRT_ASM_SFUNC_COMPILE); } else if ( !a->funcs[LCCRT_PLUGIN_ASM_FUNC_TOOL] ) { lccrt_ctx_error_plugin_sym( ctx, cur_name, LCCRT_ASM_SFUNC_GETTOOL); } } else { lccrt_assert( 0); } lname = dlsym( a->lib, LCCRT_PLUGIN_LIBRARY_NAME_S); lver = dlsym( a->lib, LCCRT_PLUGIN_LCCRT_VERSION_S); targs = dlsym( a->lib, LCCRT_PLUGIN_TARGETS_S); if ( !lname || !lname[0] ) { lccrt_ctx_error_plugin_sym( ctx, cur_name, LCCRT_PLUGIN_LIBRARY_NAME_S); } else if ( !lname[0][0] ) { lccrt_ctx_error( ctx, 0, "Plugin library [%s] name [%s] is incorrect\n", cur_name, lname[0]); } else if ( !lver || !lver[0] ) { lccrt_ctx_error_plugin_sym( ctx, cur_name, LCCRT_PLUGIN_LCCRT_VERSION_S); } else if ( !targs ) { lccrt_ctx_error_plugin_sym( ctx, cur_name, LCCRT_PLUGIN_TARGETS_S); } else { if ( ctx->verbose.is_base ) { fprintf( stderr, "LCCRT: plugin [%s] config:\n", lib_name); } a->lib_name = lccrt_ctx_copy_str( ctx, lname[0]); a->lccrt_ver = lccrt_ctx_copy_str( ctx, lver[0]); if ( ctx->verbose.is_base ) { fprintf( stderr, " plugin self-name : %s\n", a->lib_name); fprintf( stderr, " plugin's version of lccrt-library : %s\n", a->lccrt_ver); } a->num_targs = 0; for ( k = 0; (*targs)[k]; ++k ) { a->num_targs++; } if ( (0 < a->num_targs) && (a->num_targs < LCCRT_CTX_PLUGIN_TARGET_MAX_NUMBER) ) { r = 0; a->targs = lccrt_ctx_mallocn( ctx, const char *, a->num_targs); a->lccrt_s = lccrt_ctx_mallocn( ctx, const char *, a->num_targs); a->include_s = lccrt_ctx_mallocn( ctx, const char *, a->num_targs); memset( a->targs, 0, a->num_targs*sizeof( a->lccrt_s[0])); memset( a->lccrt_s, 0, a->num_targs*sizeof( a->lccrt_s[0])); memset( a->include_s, 0, a->num_targs*sizeof( a->include_s[0])); for ( k = 0; k < a->num_targs; ++k ) { char buf[1024] = {0}; a->targs[k] = lccrt_ctx_copy_str( ctx, (*targs)[k]); if ( ctx->verbose.is_base ) { fprintf( stderr, " plugin's target (%d) : %s\n", k, a->targs[k]); } snprintf( buf, 1024, "%s/lib/%s", ctx->paths.home, a->targs[k]); a->lccrt_s[k] = lccrt_ctx_copy_str( ctx, buf); if ( ctx->verbose.is_base ) { fprintf( stderr, " plugin's target system libraries path : %s\n", a->lccrt_s[k]); } snprintf( buf, 1024, "%s/include/%s", ctx->paths.home, a->targs[k]); a->include_s[k] = lccrt_ctx_copy_str( ctx, buf); if ( ctx->verbose.is_base ) { fprintf( stderr, " plugin's target system include path : %s\n", a->include_s[k]); } if ( lccrt_str_eq( a->lib_name, "lccopt-e2k64") ) { FILE *flib = 0; snprintf( buf, 1024, "%s/liblccrt_s.a", a->lccrt_s[k]); flib = fopen( buf, "r"); if ( !flib ) { r = -1; lccrt_ctx_error( ctx, 0, "Can't find system library [liblccrt_s.a] by path [%s]\n", a->lccrt_s[k]); break; } else { fclose( flib); } } } } else { a->num_targs = 0; lccrt_ctx_error( ctx, 0, "Plugin library [%s] number of targets [%d]\n", cur_name, a->num_targs); } } } lccrt_ctx_free( ctx, cur_name); if ( r ) { lccrt_ctx_plugin_unload( a); } return (r); } /* lccrt_ctx_load_plugin_lib */ /** * Поиск lccrt-home пути на основе пути к liblccrt.so (места расположения загруженной библиотеки). */ char * lccrt_ctx_find_home_path( lccrt_ctx_ptr ctx) { Dl_info dli; char *t = 0; char *s = 0; dladdr( &lccrt_ctx_find_home_path, &dli); t = realpath( dli.dli_fname, 0); if ( !t ) { lccrt_ctx_error( ctx, 0, "Can't resolve real path of lccrt-library's location [%s]\n", dli.dli_fname); } s = dirname( t); if ( !s ) { lccrt_ctx_error( ctx, 0, "Can't resolve directory of lccrt-library's location [%s]\n", t); } s = lccrt_ctx_cat_strs( ctx, s, "/lccrt"); free( t); return (s); } /* lccrt_ctx_find_home_path */ /** * Загрузка плагина. */ static int lccrt_ctx_load_plugin( lccrt_ctx_ptr ctx, lccrt_plugin_type_t type, const char *env, const char *dir) { int k; int r = 0; char *f_name = 0; FILE *f = 0; int num_ps = 0; lccrt_plugin_t ps[LCCRT_CTX_PLUGIN_MAX_NUMBER] = {0}; if ( getenv( env) ) { ctx->paths.plugins[type] = lccrt_ctx_copy_str( ctx, getenv( env)); } else { ctx->paths.plugins[type] = lccrt_ctx_cat_strs( ctx, ctx->paths.plugin, "/"); ctx->paths.plugins[type] = lccrt_ctx_cat_strs( ctx, ctx->paths.plugins[type], dir); } f_name = lccrt_ctx_cat_strs( ctx, ctx->paths.plugins[type], "/plugin.conf"); f = fopen( f_name, "r"); if ( !f ) { lccrt_ctx_error( ctx, 0, "Can't open plugin [%s] config file [%s]\n", dir, f_name); lccrt_ctx_free( ctx, f_name); r = -1; } else { char name[LCCRT_CTX_PLUGIN_NAME_LENGTH + 1]; lccrt_ctx_free( ctx, f_name); while ( !feof( f) ) { lccrt_getline( f, LCCRT_CTX_PLUGIN_NAME_LENGTH, name); if ( (name[0] == '#') || (name[0] == 0) ) { /* Пропускаем текущую строчку. */ } else { if ( (num_ps < LCCRT_CTX_PLUGIN_MAX_NUMBER) ) { int is_load = 0; lccrt_check_type_init( ps + num_ps, lccrt_plugin_t); ps[num_ps].ctx = ctx; ps[num_ps].type = type; if ( (lccrt_ctx_load_plugin_lib( ps + num_ps, name) == 0) ) { is_load = 1; num_ps++; for ( k = 0; k < num_ps - 1; ++k ) { if ( lccrt_str_eq( ps[k].lib_name, ps[num_ps-1].lib_name) ) { is_load = 0; lccrt_ctx_error( ctx, 0, "Duplicate plugin name [%s]\n", ps[k].lib_name); break; } } } if ( !is_load ) { lccrt_ctx_error( ctx, 0, "Can't load plugin [%s]\n", name); for ( k = 0; k < num_ps; ++k ) { lccrt_ctx_plugin_unload( ps + k); } lccrt_context_delete( ctx); return (0); } } } } fclose( f); if ( (num_ps == 0) ) { //lccrt_ctx_warning( ctx, 0, "The plugin [%s] set is empty\n", dir); } else { ctx->num_plgs[type] = num_ps; ctx->plgs[type] = lccrt_ctx_memdup( ctx, ps, num_ps * sizeof( ps[0])); } } return (r); } /* lccrt_ctx_load_plugin */ /** * Создание контекста (конструктор). * --------------------------------- * @param mem менеджер памяти (0 - менеджер по умолчанию) * @param err менеджер сообщений об ошибках (0 - менеджер по умолчанию) * @result новый контекст, созданный с помощью менеджера памяти * * @ingroup tyCtxFns */ lccrt_context_ptr lccrt_context_new( lccrt_mem_ptr mem, lccrt_err_ptr err) { int k; lccrt_context_ptr ctx = 0; FILE *pc = 0; if ( !mem ) { mem = &lccrt_std_mem; } if ( !err ) { err = &lccrt_std_err; } if ( getenv( "LCCRT_ERRDIR") ) { err = &lccrt_dir_err; } ctx = (*mem->palloc)( mem->pool, sizeof( lccrt_context_t)); memset( ctx, 0, sizeof( lccrt_context_t)); lccrt_check_type_init( ctx, lccrt_context_t); ctx->mem = *mem; ctx->err = *err; ctx->modules = lccrt_hash_new( ctx, LCCRT_HASH_KEY_INTPTR); ctx->module_max = 0; if ( getenv( "LCCRT_HOME") ) { ctx->paths.home = lccrt_ctx_copy_str( ctx, getenv( "LCCRT_HOME")); } else { ctx->paths.home = lccrt_ctx_find_home_path( ctx); } if ( getenv( "LCCRT_HOME_PLUGIN") ) { ctx->paths.plugin = lccrt_ctx_copy_str( ctx, getenv( "LCCRT_HOME_PLUGIN")); } else { ctx->paths.plugin = lccrt_ctx_cat_strs( ctx, ctx->paths.home, "/plugin"); } if ( getenv( "LCCRT_VERBOSE") ) { ctx->verbose.is_base = atoi( getenv( "LCCRT_VERBOSE")); } lccrt_ctx_load_plugin( ctx, LCCRT_PLUGIN_TYPE_ASM, "LCCRT_PLUGIN_TYPE_ASM", "asm"); return (ctx); } /* lccrt_context_new */ /** * Удаление контекста (деструктор). * -------------------------------- * @param ctx удаляемый контекст * * @ingroup tyCtxFns */ void lccrt_context_delete( lccrt_context_ptr ctx) { lccrt_hash_entry_ptr he; lccrt_check_type_assert( ctx, lccrt_context_t); /* Удаляем все ранее созданные модули. */ while ( (he = lccrt_hash_first( ctx->modules)) ) { lccrt_module_delete( (lccrt_module_ptr)lccrt_hash_get_key( he)); } lccrt_hash_delete( ctx->modules); lccrt_ctx_free( ctx, ctx->paths.home); lccrt_ctx_free( ctx, ctx->paths.plugin); lccrt_ctx_free( ctx, ctx->paths.plugins[LCCRT_PLUGIN_TYPE_ASM]); lccrt_check_type_done( ctx, lccrt_context_t); (*ctx->mem.pfree)( ctx->mem.pool, ctx); return; } /* lccrt_context_delete */ /** * Прочитать свойство. */ int lccrt_context_get_verbose_ir( lccrt_context_ptr ctx) { int r = ctx->verbose.is_ir; lccrt_check_type_assert( ctx, lccrt_context_t); return (r); } /* lccrt_context_get_verbose_ir */ /** * Установить свойство. */ void lccrt_context_set_verbose_ir( lccrt_context_ptr ctx, int value) { lccrt_check_type_assert( ctx, lccrt_context_t); ctx->verbose.is_ir = value; return; } /* lccrt_context_set_verbose_ir */ /** * Поиск плагина. */ static lccrt_plugin_t * lccrt_context_find_plugin( lccrt_context_ptr c, lccrt_plugin_type_t type, const char *plg_name, int is_assert) { int k; lccrt_plugin_t *r = 0; if ( plg_name ) { for ( k = 0; k < c->num_plgs[type]; ++k ) { if ( lccrt_str_eq( plg_name, c->plgs[type][k].lib_name) ) { r = c->plgs[type] + k; break; } } } if ( !r && is_assert ) { lccrt_ctx_error( c, 0, "No plugin with name [%s]\n", plg_name); } return (r); } /* lccrt_context_find_plugin */ /** * Поиск плагина. */ static lccrt_plg_ptr lccrt_context_find_plugin_for_arch( lccrt_context_ptr c, lccrt_plugin_type_t type, const char *arch) { int k, i; lccrt_plg_ptr r = 0; for ( k = 0; k < c->num_plgs[type] && !r; ++k ) { lccrt_plg_ptr p = c->plgs[type] + k; for ( i = 0; i < p->num_targs; ++i ) { if ( lccrt_str_eq( arch, p->targs[i]) ) { r = p; break; } } } if ( !r ) { lccrt_ctx_error( c, 0, "No plugin for target [%s]\n", arch); } return (r); } /* lccrt_context_find_plugin_for_arch */ /** * Получить ссылку на плагин. */ lccrt_plg_ptr lccrt_context_get_plugin_asm( lccrt_ctx_ptr ctx, const char *plg_name) { lccrt_plg_ptr r = lccrt_context_find_plugin( ctx, LCCRT_PLUGIN_TYPE_ASM, plg_name, 1); return (r); } /* lccrt_context_get_plugin_asm */ /** * Поиск ассемблера. */ static int lccrt_context_find_target( lccrt_context_ptr c, lccrt_plugin_t *a, const char *targ, int is_assert) { int k; int r = -1; if ( a ) { if ( targ ) { for ( k = 0; k < a->num_targs; ++k ) { if ( lccrt_str_eq( targ, a->targs[k]) ) { r = k; break; } } } if ( (r < 0) && is_assert ) { lccrt_ctx_error( c, 0, "In plugin [%s] no target [%s]\n", a->lib_name, targ); } } return (r); } /* lccrt_context_find_target */ /** * Компиляция модуля. */ int lccrt_module_compile_asm( lccrt_module_ptr m, const char *asm_lib, lccrt_asm_compile_config_t *cnf) { int k; int r = -1; lccrt_context_ptr c = lccrt_module_get_context( m); lccrt_plugin_t *a = lccrt_context_get_plugin_asm( c, asm_lib); if ( cnf->is_jit ) { assert( 0); } if ( 0 ) { lccrt_fs_ptr fs = lccrt_fs_new_file( c, stdout); lccrt_asm_print_module( fs, m); lccrt_fs_delete( fs); } if ( (lccrt_context_find_target( c, a, cnf->target, 1) >= 0) ) { r = ((lccrt_asm_compile_t)a->funcs[LCCRT_PLUGIN_ASM_FUNC_COMP])( m, cnf); } return (r); } /* lccrt_module_compile_asm */ /** * Получить значение утилиты. */ const char * lccrt_context_get_toolchain( lccrt_ctx_ptr c, const char *asm_lib, const char *targ, const char *tool_type, const char *tool_name) { const char *r = ""; lccrt_plugin_t *a = lccrt_context_get_plugin_asm( c, asm_lib); int k = lccrt_context_find_target( c, a, targ, 1); if ( (k >= 0) ) { if ( lccrt_str_eq( tool_type, "lib_path") && lccrt_str_eq( tool_name, "lccrt_s") ) { r = a->lccrt_s[k]; } else if ( lccrt_str_eq( tool_type, "include_path") && lccrt_str_eq( tool_name, "system") ) { r = a->include_s[k]; } else { r = ((lccrt_asm_gettool_t)a->funcs[LCCRT_PLUGIN_ASM_FUNC_TOOL])( targ, tool_type, tool_name); } } return (r); } /* lccrt_context_get_toolchain */ /** * Получить значение поля. */ lccrt_err_t lccrt_context_get_err_info( lccrt_ctx_ptr ctx) { lccrt_err_t r; lccrt_check_type_assert( ctx, lccrt_context_t); r = ctx->err; return (r); } /* lccrt_context_get_err_info */ /** * Установить значение поля. */ lccrt_err_t lccrt_context_set_err_info( lccrt_ctx_ptr ctx, lccrt_err_t err) { lccrt_err_t r; lccrt_check_type_assert( ctx, lccrt_context_t); r = ctx->err; ctx->err = err; return (r); } /* lccrt_context_set_err_info */ /** * Выделение участка памяти. */ void * lccrt_ctx_malloc_func( lccrt_ctx_ptr ctx, uint64_t size) { void *r; lccrt_check_type_assert( ctx, lccrt_context_t); r = ctx->mem.palloc( &(ctx->mem), size); return (r); } /* lccrt_ctx_malloc_func */ /** * Выделение участка памяти. */ void * lccrt_ctx_realloc_func( lccrt_ctx_ptr ctx, void *ptr, uint64_t size) { void *r; lccrt_check_type_assert( ctx, lccrt_context_t); r = ctx->mem.prealloc( &(ctx->mem), ptr, size); return (r); } /* lccrt_ctx_realloc_func */ /** * Освобождение участка памяти. */ void * lccrt_ctx_free_func( lccrt_ctx_ptr ctx, void *ptr) { lccrt_check_type_assert( ctx, lccrt_context_t); if ( ptr ) { ctx->mem.pfree( &(ctx->mem), ptr); } return (0); } /* lccrt_ctx_free_func */ /** * Копирование участка памяти. */ void * lccrt_ctx_memdup_func( lccrt_ctx_ptr ctx, void *ptr, uint64_t size) { void *r = 0; lccrt_check_type_assert( ctx, lccrt_context_t); if ( (size > 0) ) { r = ctx->mem.palloc( &(ctx->mem), size); if ( ptr ) { memcpy( r, ptr, size); } else { memset( r, 0, size); } } return (r); } /* lccrt_ctx_memdup_func */ /** * Копирование массива. */ void ** lccrt_ctx_copy_arr_func( lccrt_ctx_ptr ctx, void **ptr, uint64_t size, uint64_t len) { uint64_t k; void **r = 0; if ( (len > 0) ) { r = lccrt_ctx_malloc_func( ctx, len * sizeof( r[0])); for ( k = 0; k < len; ++k ) { r[k] = lccrt_ctx_memdup_func( ctx, ptr[k], size); } } return (r); } /* lccrt_ctx_copy_arr_func */ /** * Копирование участка памяти. */ char * lccrt_ctx_copy_str( lccrt_ctx_ptr ctx, const char *str) { void *r = 0; if ( str ) { r = (char *)lccrt_ctx_memdup_func( ctx, (void *)str, strlen( str) + 1); } return (r); } /* lccrt_ctx_copy_str */ /** * Объединение строк. */ char * lccrt_ctx_cat_strs( lccrt_ctx_ptr ctx, const char *str1, const char *str2) { char *r = 0; int len1 = str1 ? strlen( str1) : 0; int len2 = str2 ? strlen( str2) : 0; r = lccrt_ctx_malloc_func( ctx, len1 + len2 + 1); memcpy( r, str1, len1); memcpy( r + len1, str2, len2); r[len1 + len2] = 0; return (r); } /* lccrt_ctx_cat_strs */ /** * Объединение строк. */ char * lccrt_ctx_catby_strs( lccrt_ctx_ptr ctx, const char *str1, const char *str2) { char *r = lccrt_ctx_cat_strs( ctx, str1, str2); lccrt_ctx_free( ctx, str1); return (r); } /* lccrt_ctx_catby_strs */ /** * Старт внешней программы с перенаправлением стандартного потока вывода * на канальные файловые дескрипторы. */ int lccrt_exec_with_fork( const char *path, /* первый аргумент execv */ char *argv[], /* второй аргумент execv */ pid_t *wpid, int fds[2]) /* fds[0] - выходной декскриптор для внешней программы, fds[1] - входной декскриптор для внешней программы */ { pid_t pid; int ifd[2] = {-1, -1}; int ofd[2] = {-1, -1}; int r = -1; if ( wpid ) { wpid[0] = -1; } if ( fds ) { if ( (pipe( ifd) != 0) ) { /* Не удалось создать канал. */ return (r); } if ( (pipe( ofd) != 0) ) { /* Не удалось создать канал. */ return (r); } } pid = fork(); if ( (pid < 0) ) { /* Не удалось создать процесс. */ return (r); } if ( (pid == 0) ) { /* Запускаем внешнюю программу. */ if ( fds ) { close( ifd[1]); dup2( ifd[0], STDIN_FILENO); close( ifd[0]); close( ofd[0]); dup2( ofd[1], STDOUT_FILENO); dup2( ofd[1], STDERR_FILENO); close( ofd[1]); } execvp( path, argv); } else { /* Возвращаем файловые дескрипторы с вводом и выводом внешней программы. */ r = 0; if ( fds ) { close( ifd[0]); close( ofd[1]); fds[0] = ofd[0]; fds[1] = ifd[1]; } if ( wpid ) { (*wpid) = pid; } } return (r); } /* lccrt_exec_with_fork */