mirror of https://github.com/arendst/Tasmota.git
parent
21de682f58
commit
67b36030dc
|
@ -0,0 +1,38 @@
|
||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
|
project(Berry C)
|
||||||
|
set(CMAKE_C_STANDARD 99)
|
||||||
|
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||||
|
|
||||||
|
set(BERRY_COC ${CMAKE_CURRENT_SOURCE_DIR}/tools/coc/coc)
|
||||||
|
set(BERRY_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||||
|
set(BERRY_CONFIG_DIR default CACHE FILEPATH "The directory of berry_conf.h.")
|
||||||
|
set(BERRY_CONFIG ${CMAKE_CURRENT_SOURCE_DIR}/${BERRY_CONFIG_DIR}/berry_conf.h)
|
||||||
|
set(BERRY_GENERATE ${CMAKE_CURRENT_SOURCE_DIR}/generate)
|
||||||
|
|
||||||
|
if (${CMAKE_HOST_WIN32})
|
||||||
|
set(BERRY_COC python ${BERRY_COC})
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
file(MAKE_DIRECTORY generate)
|
||||||
|
|
||||||
|
# berry library
|
||||||
|
file(GLOB SOURCES src/*.c)
|
||||||
|
add_library(libberry ${SOURCES})
|
||||||
|
target_include_directories(libberry PUBLIC src ${BERRY_CONFIG_DIR})
|
||||||
|
|
||||||
|
add_custom_target(berry-coc
|
||||||
|
COMMAND ${BERRY_COC} -o ${BERRY_GENERATE} ${BERRY_SOURCE_DIR} -c ${BERRY_CONFIG}
|
||||||
|
DEPENDS ${SOURCES} COMMAND_EXPAND_LISTS
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
COMMENT "Generate coc objects"
|
||||||
|
)
|
||||||
|
add_dependencies(libberry berry-coc)
|
||||||
|
|
||||||
|
# berry default exe
|
||||||
|
file(GLOB SOURCES_EXE default/*.c)
|
||||||
|
add_executable(berry ${SOURCES_EXE})
|
||||||
|
target_link_libraries(berry PUBLIC libberry)
|
|
@ -59,6 +59,13 @@
|
||||||
FULL_VERSION " (build in " __DATE__ ", " __TIME__ ")\n" \
|
FULL_VERSION " (build in " __DATE__ ", " __TIME__ ")\n" \
|
||||||
"[" COMPILER "] on " OS_NAME " (default)\n" \
|
"[" COMPILER "] on " OS_NAME " (default)\n" \
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#define PATH_SEPARATOR ";"
|
||||||
|
#else
|
||||||
|
#define PATH_SEPARATOR ":"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* command help information */
|
/* command help information */
|
||||||
#define help_information \
|
#define help_information \
|
||||||
"Usage: berry [options] [script [args]]\n" \
|
"Usage: berry [options] [script [args]]\n" \
|
||||||
|
@ -66,6 +73,7 @@
|
||||||
" -i enter interactive mode after executing 'file'\n" \
|
" -i enter interactive mode after executing 'file'\n" \
|
||||||
" -l all variables in 'file' are parsed as local\n" \
|
" -l all variables in 'file' are parsed as local\n" \
|
||||||
" -e load 'script' source string and execute\n" \
|
" -e load 'script' source string and execute\n" \
|
||||||
|
" -m <path> custom module search path(s) separated by '" PATH_SEPARATOR "'\n"\
|
||||||
" -c <file> compile script 'file' to bytecode file\n" \
|
" -c <file> compile script 'file' to bytecode file\n" \
|
||||||
" -o <file> save bytecode to 'file'\n" \
|
" -o <file> save bytecode to 'file'\n" \
|
||||||
" -g force named globals in VM\n" \
|
" -g force named globals in VM\n" \
|
||||||
|
@ -87,6 +95,7 @@
|
||||||
#define arg_g (1 << 7)
|
#define arg_g (1 << 7)
|
||||||
#define arg_s (1 << 8)
|
#define arg_s (1 << 8)
|
||||||
#define arg_err (1 << 9)
|
#define arg_err (1 << 9)
|
||||||
|
#define arg_m (1 << 10)
|
||||||
|
|
||||||
struct arg_opts {
|
struct arg_opts {
|
||||||
int idx;
|
int idx;
|
||||||
|
@ -95,6 +104,7 @@ struct arg_opts {
|
||||||
const char *errarg;
|
const char *errarg;
|
||||||
const char *src;
|
const char *src;
|
||||||
const char *dst;
|
const char *dst;
|
||||||
|
const char *modulepath;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* check if the character is a letter */
|
/* check if the character is a letter */
|
||||||
|
@ -257,6 +267,10 @@ static int parse_arg(struct arg_opts *opt, int argc, char *argv[])
|
||||||
case 'e': args |= arg_e; break;
|
case 'e': args |= arg_e; break;
|
||||||
case 'g': args |= arg_g; break;
|
case 'g': args |= arg_g; break;
|
||||||
case 's': args |= arg_s; break;
|
case 's': args |= arg_s; break;
|
||||||
|
case 'm':
|
||||||
|
args |= arg_m;
|
||||||
|
opt->modulepath = opt->optarg;
|
||||||
|
break;
|
||||||
case '?': return args | arg_err;
|
case '?': return args | arg_err;
|
||||||
case 'c':
|
case 'c':
|
||||||
args |= arg_c;
|
args |= arg_c;
|
||||||
|
@ -286,12 +300,47 @@ static void push_args(bvm *vm, int argc, char *argv[])
|
||||||
be_pop(vm, 1);
|
be_pop(vm, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#define BERRY_ROOT "\\Windows\\system32"
|
||||||
|
static const char *module_paths[] = {
|
||||||
|
BERRY_ROOT "\\berry\\packages",
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
#define BERRY_ROOT "/usr/local"
|
||||||
|
static const char *module_paths[] = {
|
||||||
|
BERRY_ROOT "/lib/berry/packages",
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void berry_paths(bvm * vm)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < array_count(module_paths); ++i) {
|
||||||
|
be_module_path_set(vm, module_paths[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void berry_custom_paths(bvm *vm, const char *modulepath)
|
||||||
|
{
|
||||||
|
const char delim[] = PATH_SEPARATOR;
|
||||||
|
char *copy = malloc(strlen(modulepath) + 1);
|
||||||
|
strcpy(copy, modulepath);
|
||||||
|
char *ptr = strtok(copy, delim);
|
||||||
|
|
||||||
|
while (ptr != NULL) {
|
||||||
|
be_module_path_set(vm, ptr);
|
||||||
|
ptr = strtok(NULL, delim);
|
||||||
|
}
|
||||||
|
free(copy);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* command format: berry [options] [script [args]]
|
* command format: berry [options] [script [args]]
|
||||||
* command options:
|
* command options:
|
||||||
* -i: enter interactive mode after executing 'script'
|
* -i: enter interactive mode after executing 'script'
|
||||||
* -b: load code from bytecode file
|
* -b: load code from bytecode file
|
||||||
* -e: load 'script' source and execute
|
* -e: load 'script' source and execute
|
||||||
|
* -m: specify custom module search path(s)
|
||||||
* command format: berry options
|
* command format: berry options
|
||||||
* command options:
|
* command options:
|
||||||
* -v: show version information
|
* -v: show version information
|
||||||
|
@ -305,7 +354,7 @@ static int analysis_args(bvm *vm, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int args = 0;
|
int args = 0;
|
||||||
struct arg_opts opt = { 0 };
|
struct arg_opts opt = { 0 };
|
||||||
opt.pattern = "vhilegsc?o?";
|
opt.pattern = "m?vhilegsc?o?";
|
||||||
args = parse_arg(&opt, argc, argv);
|
args = parse_arg(&opt, argc, argv);
|
||||||
argc -= opt.idx;
|
argc -= opt.idx;
|
||||||
argv += opt.idx;
|
argv += opt.idx;
|
||||||
|
@ -315,6 +364,16 @@ static int analysis_args(bvm *vm, int argc, char *argv[])
|
||||||
be_pop(vm, 1);
|
be_pop(vm, 1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (args & arg_m) {
|
||||||
|
berry_custom_paths(vm, opt.modulepath);
|
||||||
|
args &= ~arg_m;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// use default module paths
|
||||||
|
berry_paths(vm);
|
||||||
|
}
|
||||||
|
|
||||||
if (args & arg_g) {
|
if (args & arg_g) {
|
||||||
comp_set_named_gbl(vm); /* forced named global in VM code */
|
comp_set_named_gbl(vm); /* forced named global in VM code */
|
||||||
args &= ~arg_g; /* clear the flag for this option not to interfere with other options */
|
args &= ~arg_g; /* clear the flag for this option not to interfere with other options */
|
||||||
|
@ -339,31 +398,11 @@ static int analysis_args(bvm *vm, int argc, char *argv[])
|
||||||
return load_script(vm, argc, argv, args);
|
return load_script(vm, argc, argv, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#define BERRY_ROOT "\\Windows\\system32"
|
|
||||||
static const char *module_paths[] = {
|
|
||||||
BERRY_ROOT "\\berry\\packages",
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
#define BERRY_ROOT "/usr/local"
|
|
||||||
static const char *module_paths[] = {
|
|
||||||
BERRY_ROOT "/lib/berry/packages",
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void berry_paths(bvm * vm)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
for (i = 0; i < array_count(module_paths); ++i) {
|
|
||||||
be_module_path_set(vm, module_paths[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
bvm *vm = be_vm_new(); /* create a virtual machine instance */
|
bvm *vm = be_vm_new(); /* create a virtual machine instance */
|
||||||
berry_paths(vm);
|
|
||||||
res = analysis_args(vm, argc, argv);
|
res = analysis_args(vm, argc, argv);
|
||||||
be_vm_delete(vm); /* free all objects and vm */
|
be_vm_delete(vm); /* free all objects and vm */
|
||||||
return res;
|
return res;
|
||||||
|
|
|
@ -26,12 +26,43 @@
|
||||||
#define realloc BE_EXPLICIT_REALLOC
|
#define realloc BE_EXPLICIT_REALLOC
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void* malloc_from_pool(bvm *vm, size_t size);
|
|
||||||
static void free_from_pool(bvm *vm, void* ptr, size_t old_size);
|
|
||||||
|
|
||||||
#define POOL16_SIZE 16
|
#define POOL16_SIZE 16
|
||||||
#define POOL32_SIZE 32
|
#define POOL32_SIZE 32
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#include <intrin.h>
|
||||||
|
#pragma intrinsic(_BitScanForward)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#define popcount(v) __builtin_popcount(v)
|
||||||
|
#define ffs(v) __builtin_ffs(v)
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
#define popcount(v) __popcnt(v)
|
||||||
|
|
||||||
|
static int ffs(unsigned x)
|
||||||
|
{
|
||||||
|
unsigned long i;
|
||||||
|
return _BitScanForward(&i, x) ? i : 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* https://github.com/hcs0/Hackers-Delight/blob/master/pop.c.txt - count number of 1-bits */
|
||||||
|
static int popcount(uint32_t n)
|
||||||
|
{
|
||||||
|
n = (n & 0x55555555u) + ((n >> 1) & 0x55555555u);
|
||||||
|
n = (n & 0x33333333u) + ((n >> 2) & 0x33333333u);
|
||||||
|
n = (n & 0x0f0f0f0fu) + ((n >> 4) & 0x0f0f0f0fu);
|
||||||
|
n = (n & 0x00ff00ffu) + ((n >> 8) & 0x00ff00ffu);
|
||||||
|
n = (n & 0x0000ffffu) + ((n >>16) & 0x0000ffffu);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
#error "unsupport compiler for ffs()"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void* malloc_from_pool(bvm *vm, size_t size);
|
||||||
|
static void free_from_pool(bvm *vm, void* ptr, size_t old_size);
|
||||||
|
|
||||||
BERRY_API void* be_os_malloc(size_t size)
|
BERRY_API void* be_os_malloc(size_t size)
|
||||||
{
|
{
|
||||||
return malloc(size);
|
return malloc(size);
|
||||||
|
@ -66,7 +97,7 @@ BERRY_API void* be_realloc(bvm *vm, void *ptr, size_t old_size, size_t new_size)
|
||||||
if (!ptr || (old_size == 0)) {
|
if (!ptr || (old_size == 0)) {
|
||||||
block = malloc_from_pool(vm, new_size);
|
block = malloc_from_pool(vm, new_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Case 2: deallocate */
|
/* Case 2: deallocate */
|
||||||
else if (new_size == 0) {
|
else if (new_size == 0) {
|
||||||
#if BE_USE_PERF_COUNTERS
|
#if BE_USE_PERF_COUNTERS
|
||||||
|
@ -176,11 +207,7 @@ static void* malloc_from_pool(bvm *vm, size_t size) {
|
||||||
/* look for an empty slot */
|
/* look for an empty slot */
|
||||||
if (pool16->bitmap != 0x0000) {
|
if (pool16->bitmap != 0x0000) {
|
||||||
/* there is a free slot */
|
/* there is a free slot */
|
||||||
#ifdef __GNUC__
|
|
||||||
int bit = __builtin_ffs(pool16->bitmap) - 1;
|
|
||||||
#else
|
|
||||||
int bit = ffs(pool16->bitmap) - 1;
|
int bit = ffs(pool16->bitmap) - 1;
|
||||||
#endif
|
|
||||||
if (bit >= 0) {
|
if (bit >= 0) {
|
||||||
/* we found a free slot */
|
/* we found a free slot */
|
||||||
// bitClear(pool16->bitmap, bit);
|
// bitClear(pool16->bitmap, bit);
|
||||||
|
@ -208,11 +235,7 @@ static void* malloc_from_pool(bvm *vm, size_t size) {
|
||||||
/* look for an empty slot */
|
/* look for an empty slot */
|
||||||
if (pool32->bitmap != 0x0000) {
|
if (pool32->bitmap != 0x0000) {
|
||||||
/* there is a free slot */
|
/* there is a free slot */
|
||||||
#ifdef __GNUC__
|
|
||||||
int bit = __builtin_ffs(pool32->bitmap) - 1;
|
|
||||||
#else
|
|
||||||
int bit = ffs(pool32->bitmap) - 1;
|
int bit = ffs(pool32->bitmap) - 1;
|
||||||
#endif
|
|
||||||
if (bit >= 0) {
|
if (bit >= 0) {
|
||||||
/* we found a free slot */
|
/* we found a free slot */
|
||||||
// bitClear(pool32->bitmap, bit);
|
// bitClear(pool32->bitmap, bit);
|
||||||
|
@ -327,24 +350,6 @@ BERRY_API void be_gc_free_memory_pools(bvm *vm) {
|
||||||
vm->gc.pool32 = NULL;
|
vm->gc.pool32 = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* https://github.com/hcs0/Hackers-Delight/blob/master/pop.c.txt - count number of 1-bits */
|
|
||||||
static int pop0(uint32_t n) __attribute__((unused));
|
|
||||||
static int pop0(uint32_t n) {
|
|
||||||
n = (n & 0x55555555u) + ((n >> 1) & 0x55555555u);
|
|
||||||
n = (n & 0x33333333u) + ((n >> 2) & 0x33333333u);
|
|
||||||
n = (n & 0x0f0f0f0fu) + ((n >> 4) & 0x0f0f0f0fu);
|
|
||||||
n = (n & 0x00ff00ffu) + ((n >> 8) & 0x00ff00ffu);
|
|
||||||
n = (n & 0x0000ffffu) + ((n >>16) & 0x0000ffffu);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
#define count_bits_1(v) __builtin_popcount(v)
|
|
||||||
#else
|
|
||||||
#define count_bits_1(v) pop0(v)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
BERRY_API void be_gc_memory_pools_info(bvm *vm, size_t* slots_used, size_t* slots_allocated) {
|
BERRY_API void be_gc_memory_pools_info(bvm *vm, size_t* slots_used, size_t* slots_allocated) {
|
||||||
size_t used = 0;
|
size_t used = 0;
|
||||||
size_t allocated = 0;
|
size_t allocated = 0;
|
||||||
|
@ -352,14 +357,14 @@ BERRY_API void be_gc_memory_pools_info(bvm *vm, size_t* slots_used, size_t* slot
|
||||||
gc16_t* pool16 = vm->gc.pool16;
|
gc16_t* pool16 = vm->gc.pool16;
|
||||||
while (pool16) {
|
while (pool16) {
|
||||||
allocated += POOL16_SLOTS;
|
allocated += POOL16_SLOTS;
|
||||||
used += POOL16_SLOTS - count_bits_1(pool16->bitmap);
|
used += POOL16_SLOTS - popcount(pool16->bitmap);
|
||||||
pool16 = pool16->next;
|
pool16 = pool16->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
gc32_t* pool32 = vm->gc.pool32;
|
gc32_t* pool32 = vm->gc.pool32;
|
||||||
while (pool32) {
|
while (pool32) {
|
||||||
allocated += POOL32_SLOTS;
|
allocated += POOL32_SLOTS;
|
||||||
used += POOL32_SLOTS - count_bits_1(pool32->bitmap);
|
used += POOL32_SLOTS - popcount(pool32->bitmap);
|
||||||
pool32 = pool32->next;
|
pool32 = pool32->next;
|
||||||
}
|
}
|
||||||
if (slots_used) { *slots_used = used; }
|
if (slots_used) { *slots_used = used; }
|
||||||
|
|
Loading…
Reference in New Issue