mirror of
https://github.com/luau-lang/luau.git
synced 2024-12-14 22:21:10 +00:00
594 lines
18 KiB
C
594 lines
18 KiB
C
/* ----------------------------------------------------------------------------
|
|
Copyright (c) 2021, Daan Leijen
|
|
This is free software; you can redistribute it and/or modify it
|
|
under the terms of the MIT License. A copy of the license can be
|
|
found in the "LICENSE" file at the root of this distribution.
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
//-------------------------------------------------------------
|
|
// Usually we include all sources one file so no internal
|
|
// symbols are public in the libray.
|
|
//
|
|
// You can compile the entire library just as:
|
|
// $ gcc -c src/isocline.c
|
|
//-------------------------------------------------------------
|
|
#if !defined(IC_SEPARATE_OBJS)
|
|
# ifndef _CRT_NONSTDC_NO_WARNINGS
|
|
# define _CRT_NONSTDC_NO_WARNINGS // for msvc
|
|
# endif
|
|
# ifndef _CRT_SECURE_NO_WARNINGS
|
|
# define _CRT_SECURE_NO_WARNINGS // for msvc
|
|
# endif
|
|
# define _XOPEN_SOURCE 700 // for wcwidth
|
|
# define _DEFAULT_SOURCE // ensure usleep stays visible with _XOPEN_SOURCE >= 700
|
|
# include "attr.c"
|
|
# include "bbcode.c"
|
|
# include "editline.c"
|
|
# include "highlight.c"
|
|
# include "undo.c"
|
|
# include "history.c"
|
|
# include "completers.c"
|
|
# include "completions.c"
|
|
# include "term.c"
|
|
# include "tty_esc.c"
|
|
# include "tty.c"
|
|
# include "stringbuf.c"
|
|
# include "common.c"
|
|
#endif
|
|
|
|
//-------------------------------------------------------------
|
|
// includes
|
|
//-------------------------------------------------------------
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
|
|
#include "../include/isocline.h"
|
|
#include "common.h"
|
|
#include "env.h"
|
|
|
|
|
|
//-------------------------------------------------------------
|
|
// Readline
|
|
//-------------------------------------------------------------
|
|
|
|
static char* ic_getline( alloc_t* mem );
|
|
|
|
ic_public char* ic_readline(const char* prompt_text)
|
|
{
|
|
ic_env_t* env = ic_get_env();
|
|
if (env == NULL) return NULL;
|
|
if (!env->noedit) {
|
|
// terminal editing enabled
|
|
return ic_editline(env, prompt_text); // in editline.c
|
|
}
|
|
else {
|
|
// no editing capability (pipe, dumb terminal, etc)
|
|
if (env->tty != NULL && env->term != NULL) {
|
|
// if the terminal is not interactive, but we are reading from the tty (keyboard), we display a prompt
|
|
term_start_raw(env->term); // set utf8 mode on windows
|
|
if (prompt_text != NULL) {
|
|
term_write(env->term, prompt_text);
|
|
}
|
|
term_write(env->term, env->prompt_marker);
|
|
term_end_raw(env->term, false);
|
|
}
|
|
// read directly from stdin
|
|
return ic_getline(env->mem);
|
|
}
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------
|
|
// Read a line from the stdin stream if there is no editing
|
|
// support (like from a pipe, file, or dumb terminal).
|
|
//-------------------------------------------------------------
|
|
|
|
static char* ic_getline(alloc_t* mem)
|
|
{
|
|
// read until eof or newline
|
|
stringbuf_t* sb = sbuf_new(mem);
|
|
int c;
|
|
while (true) {
|
|
c = fgetc(stdin);
|
|
if (c==EOF || c=='\n') {
|
|
break;
|
|
}
|
|
else {
|
|
sbuf_append_char(sb, (char)c);
|
|
}
|
|
}
|
|
return sbuf_free_dup(sb);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------
|
|
// Formatted output
|
|
//-------------------------------------------------------------
|
|
|
|
|
|
ic_public void ic_printf(const char* fmt, ...) {
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
ic_vprintf(fmt, ap);
|
|
va_end(ap);
|
|
}
|
|
|
|
ic_public void ic_vprintf(const char* fmt, va_list args) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL || env->bbcode == NULL) return;
|
|
bbcode_vprintf(env->bbcode, fmt, args);
|
|
}
|
|
|
|
ic_public void ic_print(const char* s) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL || env->bbcode==NULL) return;
|
|
bbcode_print(env->bbcode, s);
|
|
}
|
|
|
|
ic_public void ic_println(const char* s) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL || env->bbcode==NULL) return;
|
|
bbcode_println(env->bbcode, s);
|
|
}
|
|
|
|
void ic_style_def(const char* name, const char* fmt) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL || env->bbcode==NULL) return;
|
|
bbcode_style_def(env->bbcode, name, fmt);
|
|
}
|
|
|
|
void ic_style_open(const char* fmt) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL || env->bbcode==NULL) return;
|
|
bbcode_style_open(env->bbcode, fmt);
|
|
}
|
|
|
|
void ic_style_close(void) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL || env->bbcode==NULL) return;
|
|
bbcode_style_close(env->bbcode, NULL);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------
|
|
// Interface
|
|
//-------------------------------------------------------------
|
|
|
|
ic_public bool ic_async_stop(void) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return false;
|
|
if (env->tty==NULL) return false;
|
|
return tty_async_stop(env->tty);
|
|
}
|
|
|
|
static void set_prompt_marker(ic_env_t* env, const char* prompt_marker, const char* cprompt_marker) {
|
|
if (prompt_marker == NULL) prompt_marker = "> ";
|
|
if (cprompt_marker == NULL) cprompt_marker = prompt_marker;
|
|
mem_free(env->mem, env->prompt_marker);
|
|
mem_free(env->mem, env->cprompt_marker);
|
|
env->prompt_marker = mem_strdup(env->mem, prompt_marker);
|
|
env->cprompt_marker = mem_strdup(env->mem, cprompt_marker);
|
|
}
|
|
|
|
ic_public const char* ic_get_prompt_marker(void) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return NULL;
|
|
return env->prompt_marker;
|
|
}
|
|
|
|
ic_public const char* ic_get_continuation_prompt_marker(void) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return NULL;
|
|
return env->cprompt_marker;
|
|
}
|
|
|
|
ic_public void ic_set_prompt_marker( const char* prompt_marker, const char* cprompt_marker ) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return;
|
|
set_prompt_marker(env, prompt_marker, cprompt_marker);
|
|
}
|
|
|
|
ic_public bool ic_enable_multiline( bool enable ) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return false;
|
|
bool prev = env->singleline_only;
|
|
env->singleline_only = !enable;
|
|
return !prev;
|
|
}
|
|
|
|
ic_public bool ic_enable_beep( bool enable ) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return false;
|
|
return term_enable_beep(env->term, enable);
|
|
}
|
|
|
|
ic_public bool ic_enable_color( bool enable ) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return false;
|
|
return term_enable_color( env->term, enable );
|
|
}
|
|
|
|
ic_public bool ic_enable_history_duplicates( bool enable ) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return false;
|
|
return history_enable_duplicates(env->history, enable);
|
|
}
|
|
|
|
ic_public void ic_set_history(const char* fname, long max_entries ) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return;
|
|
history_load_from(env->history, fname, max_entries );
|
|
}
|
|
|
|
ic_public void ic_history_remove_last(void) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return;
|
|
history_remove_last(env->history);
|
|
}
|
|
|
|
ic_public void ic_history_add( const char* entry ) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return;
|
|
history_push( env->history, entry );
|
|
}
|
|
|
|
ic_public void ic_history_clear(void) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return;
|
|
history_clear(env->history);
|
|
}
|
|
|
|
ic_public bool ic_enable_auto_tab( bool enable ) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return false;
|
|
bool prev = env->complete_autotab;
|
|
env->complete_autotab = enable;
|
|
return prev;
|
|
}
|
|
|
|
ic_public bool ic_enable_completion_preview( bool enable ) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return false;
|
|
bool prev = env->complete_nopreview;
|
|
env->complete_nopreview = !enable;
|
|
return !prev;
|
|
}
|
|
|
|
ic_public bool ic_enable_multiline_indent(bool enable) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return false;
|
|
bool prev = env->no_multiline_indent;
|
|
env->no_multiline_indent = !enable;
|
|
return !prev;
|
|
}
|
|
|
|
ic_public bool ic_enable_hint(bool enable) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return false;
|
|
bool prev = env->no_hint;
|
|
env->no_hint = !enable;
|
|
return !prev;
|
|
}
|
|
|
|
ic_public long ic_set_hint_delay(long delay_ms) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return false;
|
|
long prev = env->hint_delay;
|
|
env->hint_delay = (delay_ms < 0 ? 0 : (delay_ms > 5000 ? 5000 : delay_ms));
|
|
return prev;
|
|
}
|
|
|
|
ic_public void ic_set_tty_esc_delay(long initial_delay_ms, long followup_delay_ms ) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return;
|
|
if (env->tty == NULL) return;
|
|
tty_set_esc_delay(env->tty, initial_delay_ms, followup_delay_ms);
|
|
}
|
|
|
|
|
|
ic_public bool ic_enable_highlight(bool enable) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return false;
|
|
bool prev = env->no_highlight;
|
|
env->no_highlight = !enable;
|
|
return !prev;
|
|
}
|
|
|
|
ic_public bool ic_enable_inline_help(bool enable) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return false;
|
|
bool prev = env->no_help;
|
|
env->no_help = !enable;
|
|
return !prev;
|
|
}
|
|
|
|
ic_public bool ic_enable_brace_matching(bool enable) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return false;
|
|
bool prev = env->no_bracematch;
|
|
env->no_bracematch = !enable;
|
|
return !prev;
|
|
}
|
|
|
|
ic_public void ic_set_matching_braces(const char* brace_pairs) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return;
|
|
mem_free(env->mem, env->match_braces);
|
|
env->match_braces = NULL;
|
|
if (brace_pairs != NULL) {
|
|
ssize_t len = ic_strlen(brace_pairs);
|
|
if (len > 0 && (len % 2) == 0) {
|
|
env->match_braces = mem_strdup(env->mem, brace_pairs);
|
|
}
|
|
}
|
|
}
|
|
|
|
ic_public bool ic_enable_brace_insertion(bool enable) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return false;
|
|
bool prev = env->no_autobrace;
|
|
env->no_autobrace = !enable;
|
|
return !prev;
|
|
}
|
|
|
|
ic_public void ic_set_insertion_braces(const char* brace_pairs) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return;
|
|
mem_free(env->mem, env->auto_braces);
|
|
env->auto_braces = NULL;
|
|
if (brace_pairs != NULL) {
|
|
ssize_t len = ic_strlen(brace_pairs);
|
|
if (len > 0 && (len % 2) == 0) {
|
|
env->auto_braces = mem_strdup(env->mem, brace_pairs);
|
|
}
|
|
}
|
|
}
|
|
|
|
ic_private const char* ic_env_get_match_braces(ic_env_t* env) {
|
|
return (env->match_braces == NULL ? "()[]{}" : env->match_braces);
|
|
}
|
|
|
|
ic_private const char* ic_env_get_auto_braces(ic_env_t* env) {
|
|
return (env->auto_braces == NULL ? "()[]{}\"\"''" : env->auto_braces);
|
|
}
|
|
|
|
ic_public void ic_set_default_highlighter(ic_highlight_fun_t* highlighter, void* arg) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return;
|
|
env->highlighter = highlighter;
|
|
env->highlighter_arg = arg;
|
|
}
|
|
|
|
|
|
ic_public void ic_free( void* p ) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return;
|
|
mem_free(env->mem, p);
|
|
}
|
|
|
|
ic_public void* ic_malloc(size_t sz) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return NULL;
|
|
return mem_malloc(env->mem, to_ssize_t(sz));
|
|
}
|
|
|
|
ic_public const char* ic_strdup( const char* s ) {
|
|
if (s==NULL) return NULL;
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return NULL;
|
|
ssize_t len = ic_strlen(s);
|
|
char* p = mem_malloc_tp_n( env->mem, char, len + 1 );
|
|
if (p == NULL) return NULL;
|
|
ic_memcpy( p, s, len );
|
|
p[len] = 0;
|
|
return p;
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
// Terminal
|
|
//-------------------------------------------------------------
|
|
|
|
ic_public void ic_term_init(void) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return;
|
|
if (env->term==NULL) return;
|
|
term_start_raw(env->term);
|
|
}
|
|
|
|
ic_public void ic_term_done(void) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return;
|
|
if (env->term==NULL) return;
|
|
term_end_raw(env->term,false);
|
|
}
|
|
|
|
ic_public void ic_term_flush(void) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return;
|
|
if (env->term==NULL) return;
|
|
term_flush(env->term);
|
|
}
|
|
|
|
ic_public void ic_term_write(const char* s) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return;
|
|
if (env->term == NULL) return;
|
|
term_write(env->term, s);
|
|
}
|
|
|
|
ic_public void ic_term_writeln(const char* s) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return;
|
|
if (env->term == NULL) return;
|
|
term_writeln(env->term, s);
|
|
}
|
|
|
|
ic_public void ic_term_writef(const char* fmt, ...) {
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
ic_term_vwritef(fmt, ap);
|
|
va_end(ap);
|
|
}
|
|
|
|
ic_public void ic_term_vwritef(const char* fmt, va_list args) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return;
|
|
if (env->term == NULL) return;
|
|
term_vwritef(env->term, fmt, args);
|
|
}
|
|
|
|
ic_public void ic_term_reset( void ) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return;
|
|
if (env->term == NULL) return;
|
|
term_attr_reset(env->term);
|
|
}
|
|
|
|
ic_public void ic_term_style( const char* style ) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL) return;
|
|
if (env->term == NULL || env->bbcode == NULL) return;
|
|
term_set_attr( env->term, bbcode_style(env->bbcode, style));
|
|
}
|
|
|
|
ic_public int ic_term_get_color_bits(void) {
|
|
ic_env_t* env = ic_get_env();
|
|
if (env==NULL || env->term==NULL) return 4;
|
|
return term_get_color_bits(env->term);
|
|
}
|
|
|
|
ic_public void ic_term_bold(bool enable) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL || env->term==NULL) return;
|
|
term_bold(env->term, enable);
|
|
}
|
|
|
|
ic_public void ic_term_underline(bool enable) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL || env->term==NULL) return;
|
|
term_underline(env->term, enable);
|
|
}
|
|
|
|
ic_public void ic_term_italic(bool enable) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL || env->term==NULL) return;
|
|
term_italic(env->term, enable);
|
|
}
|
|
|
|
ic_public void ic_term_reverse(bool enable) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL || env->term==NULL) return;
|
|
term_reverse(env->term, enable);
|
|
}
|
|
|
|
ic_public void ic_term_color_ansi(bool foreground, int ansi_color) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL || env->term==NULL) return;
|
|
ic_color_t color = color_from_ansi256(ansi_color);
|
|
if (foreground) { term_color(env->term, color); }
|
|
else { term_bgcolor(env->term, color); }
|
|
}
|
|
|
|
ic_public void ic_term_color_rgb(bool foreground, uint32_t hcolor) {
|
|
ic_env_t* env = ic_get_env(); if (env==NULL || env->term==NULL) return;
|
|
ic_color_t color = ic_rgb(hcolor);
|
|
if (foreground) { term_color(env->term, color); }
|
|
else { term_bgcolor(env->term, color); }
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------
|
|
// Readline with temporary completer and highlighter
|
|
//-------------------------------------------------------------
|
|
|
|
ic_public char* ic_readline_ex(const char* prompt_text,
|
|
ic_completer_fun_t* completer, void* completer_arg,
|
|
ic_highlight_fun_t* highlighter, void* highlighter_arg )
|
|
{
|
|
ic_env_t* env = ic_get_env(); if (env == NULL) return NULL;
|
|
// save previous
|
|
ic_completer_fun_t* prev_completer;
|
|
void* prev_completer_arg;
|
|
completions_get_completer(env->completions, &prev_completer, &prev_completer_arg);
|
|
ic_highlight_fun_t* prev_highlighter = env->highlighter;
|
|
void* prev_highlighter_arg = env->highlighter_arg;
|
|
// call with current
|
|
if (completer != NULL) { ic_set_default_completer(completer, completer_arg); }
|
|
if (highlighter != NULL) { ic_set_default_highlighter(highlighter, highlighter_arg); }
|
|
char* res = ic_readline(prompt_text);
|
|
// restore previous
|
|
ic_set_default_completer(prev_completer, prev_completer_arg);
|
|
ic_set_default_highlighter(prev_highlighter, prev_highlighter_arg);
|
|
return res;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------
|
|
// Initialize
|
|
//-------------------------------------------------------------
|
|
|
|
static void ic_atexit(void);
|
|
|
|
static void ic_env_free(ic_env_t* env) {
|
|
if (env == NULL) return;
|
|
history_save(env->history);
|
|
history_free(env->history);
|
|
completions_free(env->completions);
|
|
bbcode_free(env->bbcode);
|
|
term_free(env->term);
|
|
tty_free(env->tty);
|
|
mem_free(env->mem, env->cprompt_marker);
|
|
mem_free(env->mem,env->prompt_marker);
|
|
mem_free(env->mem, env->match_braces);
|
|
mem_free(env->mem, env->auto_braces);
|
|
env->prompt_marker = NULL;
|
|
|
|
// and deallocate ourselves
|
|
alloc_t* mem = env->mem;
|
|
mem_free(mem, env);
|
|
|
|
// and finally the custom memory allocation structure
|
|
mem_free(mem, mem);
|
|
}
|
|
|
|
|
|
static ic_env_t* ic_env_create( ic_malloc_fun_t* _malloc, ic_realloc_fun_t* _realloc, ic_free_fun_t* _free )
|
|
{
|
|
if (_malloc == NULL) _malloc = &malloc;
|
|
if (_realloc == NULL) _realloc = &realloc;
|
|
if (_free == NULL) _free = &free;
|
|
// allocate
|
|
alloc_t* mem = (alloc_t*)_malloc(sizeof(alloc_t));
|
|
if (mem == NULL) return NULL;
|
|
mem->malloc = _malloc;
|
|
mem->realloc = _realloc;
|
|
mem->free = _free;
|
|
ic_env_t* env = mem_zalloc_tp(mem, ic_env_t);
|
|
if (env==NULL) {
|
|
mem->free(mem);
|
|
return NULL;
|
|
}
|
|
env->mem = mem;
|
|
|
|
// Initialize
|
|
env->tty = tty_new(env->mem, -1); // can return NULL
|
|
env->term = term_new(env->mem, env->tty, false, false, -1 );
|
|
env->history = history_new(env->mem);
|
|
env->completions = completions_new(env->mem);
|
|
env->bbcode = bbcode_new(env->mem, env->term);
|
|
env->hint_delay = 400;
|
|
|
|
if (env->tty == NULL || env->term==NULL ||
|
|
env->completions == NULL || env->history == NULL || env->bbcode == NULL ||
|
|
!term_is_interactive(env->term))
|
|
{
|
|
env->noedit = true;
|
|
}
|
|
env->multiline_eol = '\\';
|
|
|
|
bbcode_style_def(env->bbcode, "ic-prompt", "ansi-green" );
|
|
bbcode_style_def(env->bbcode, "ic-info", "ansi-darkgray" );
|
|
bbcode_style_def(env->bbcode, "ic-diminish", "ansi-lightgray" );
|
|
bbcode_style_def(env->bbcode, "ic-emphasis", "#ffffd7" );
|
|
bbcode_style_def(env->bbcode, "ic-hint", "ansi-darkgray" );
|
|
bbcode_style_def(env->bbcode, "ic-error", "#d70000" );
|
|
bbcode_style_def(env->bbcode, "ic-bracematch","ansi-white"); // color = #F7DC6F" );
|
|
|
|
bbcode_style_def(env->bbcode, "keyword", "#569cd6" );
|
|
bbcode_style_def(env->bbcode, "control", "#c586c0" );
|
|
bbcode_style_def(env->bbcode, "number", "#b5cea8" );
|
|
bbcode_style_def(env->bbcode, "string", "#ce9178" );
|
|
bbcode_style_def(env->bbcode, "comment", "#6A9955" );
|
|
bbcode_style_def(env->bbcode, "type", "darkcyan" );
|
|
bbcode_style_def(env->bbcode, "constant", "#569cd6" );
|
|
|
|
set_prompt_marker(env, NULL, NULL);
|
|
return env;
|
|
}
|
|
|
|
static ic_env_t* rpenv;
|
|
|
|
static void ic_atexit(void) {
|
|
if (rpenv != NULL) {
|
|
ic_env_free(rpenv);
|
|
rpenv = NULL;
|
|
}
|
|
}
|
|
|
|
ic_private ic_env_t* ic_get_env(void) {
|
|
if (rpenv==NULL) {
|
|
rpenv = ic_env_create( NULL, NULL, NULL );
|
|
if (rpenv != NULL) { atexit( &ic_atexit ); }
|
|
}
|
|
return rpenv;
|
|
}
|
|
|
|
ic_public void ic_init_custom_malloc( ic_malloc_fun_t* _malloc, ic_realloc_fun_t* _realloc, ic_free_fun_t* _free ) {
|
|
assert(rpenv == NULL);
|
|
if (rpenv != NULL) {
|
|
ic_env_free(rpenv);
|
|
rpenv = ic_env_create( _malloc, _realloc, _free );
|
|
}
|
|
else {
|
|
rpenv = ic_env_create( _malloc, _realloc, _free );
|
|
if (rpenv != NULL) {
|
|
atexit( &ic_atexit );
|
|
}
|
|
}
|
|
}
|
|
|