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" \
|
||||
"[" COMPILER "] on " OS_NAME " (default)\n" \
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define PATH_SEPARATOR ";"
|
||||
#else
|
||||
#define PATH_SEPARATOR ":"
|
||||
#endif
|
||||
|
||||
|
||||
/* command help information */
|
||||
#define help_information \
|
||||
"Usage: berry [options] [script [args]]\n" \
|
||||
|
@ -66,6 +73,7 @@
|
|||
" -i enter interactive mode after executing 'file'\n" \
|
||||
" -l all variables in 'file' are parsed as local\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" \
|
||||
" -o <file> save bytecode to 'file'\n" \
|
||||
" -g force named globals in VM\n" \
|
||||
|
@ -87,6 +95,7 @@
|
|||
#define arg_g (1 << 7)
|
||||
#define arg_s (1 << 8)
|
||||
#define arg_err (1 << 9)
|
||||
#define arg_m (1 << 10)
|
||||
|
||||
struct arg_opts {
|
||||
int idx;
|
||||
|
@ -95,6 +104,7 @@ struct arg_opts {
|
|||
const char *errarg;
|
||||
const char *src;
|
||||
const char *dst;
|
||||
const char *modulepath;
|
||||
};
|
||||
|
||||
/* 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 'g': args |= arg_g; break;
|
||||
case 's': args |= arg_s; break;
|
||||
case 'm':
|
||||
args |= arg_m;
|
||||
opt->modulepath = opt->optarg;
|
||||
break;
|
||||
case '?': return args | arg_err;
|
||||
case 'c':
|
||||
args |= arg_c;
|
||||
|
@ -286,12 +300,47 @@ static void push_args(bvm *vm, int argc, char *argv[])
|
|||
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 options:
|
||||
* -i: enter interactive mode after executing 'script'
|
||||
* -b: load code from bytecode file
|
||||
* -e: load 'script' source and execute
|
||||
* -m: specify custom module search path(s)
|
||||
* command format: berry options
|
||||
* command options:
|
||||
* -v: show version information
|
||||
|
@ -305,7 +354,7 @@ static int analysis_args(bvm *vm, int argc, char *argv[])
|
|||
{
|
||||
int args = 0;
|
||||
struct arg_opts opt = { 0 };
|
||||
opt.pattern = "vhilegsc?o?";
|
||||
opt.pattern = "m?vhilegsc?o?";
|
||||
args = parse_arg(&opt, argc, argv);
|
||||
argc -= opt.idx;
|
||||
argv += opt.idx;
|
||||
|
@ -315,6 +364,16 @@ static int analysis_args(bvm *vm, int argc, char *argv[])
|
|||
be_pop(vm, 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) {
|
||||
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 */
|
||||
|
@ -339,31 +398,11 @@ static int analysis_args(bvm *vm, int argc, char *argv[])
|
|||
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 res;
|
||||
bvm *vm = be_vm_new(); /* create a virtual machine instance */
|
||||
berry_paths(vm);
|
||||
res = analysis_args(vm, argc, argv);
|
||||
be_vm_delete(vm); /* free all objects and vm */
|
||||
return res;
|
||||
|
|
|
@ -26,12 +26,43 @@
|
|||
#define realloc BE_EXPLICIT_REALLOC
|
||||
#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 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)
|
||||
{
|
||||
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)) {
|
||||
block = malloc_from_pool(vm, new_size);
|
||||
}
|
||||
|
||||
|
||||
/* Case 2: deallocate */
|
||||
else if (new_size == 0) {
|
||||
#if BE_USE_PERF_COUNTERS
|
||||
|
@ -176,11 +207,7 @@ static void* malloc_from_pool(bvm *vm, size_t size) {
|
|||
/* look for an empty slot */
|
||||
if (pool16->bitmap != 0x0000) {
|
||||
/* there is a free slot */
|
||||
#ifdef __GNUC__
|
||||
int bit = __builtin_ffs(pool16->bitmap) - 1;
|
||||
#else
|
||||
int bit = ffs(pool16->bitmap) - 1;
|
||||
#endif
|
||||
if (bit >= 0) {
|
||||
/* we found a free slot */
|
||||
// bitClear(pool16->bitmap, bit);
|
||||
|
@ -208,11 +235,7 @@ static void* malloc_from_pool(bvm *vm, size_t size) {
|
|||
/* look for an empty slot */
|
||||
if (pool32->bitmap != 0x0000) {
|
||||
/* there is a free slot */
|
||||
#ifdef __GNUC__
|
||||
int bit = __builtin_ffs(pool32->bitmap) - 1;
|
||||
#else
|
||||
int bit = ffs(pool32->bitmap) - 1;
|
||||
#endif
|
||||
if (bit >= 0) {
|
||||
/* we found a free slot */
|
||||
// bitClear(pool32->bitmap, bit);
|
||||
|
@ -327,24 +350,6 @@ BERRY_API void be_gc_free_memory_pools(bvm *vm) {
|
|||
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) {
|
||||
size_t used = 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;
|
||||
while (pool16) {
|
||||
allocated += POOL16_SLOTS;
|
||||
used += POOL16_SLOTS - count_bits_1(pool16->bitmap);
|
||||
used += POOL16_SLOTS - popcount(pool16->bitmap);
|
||||
pool16 = pool16->next;
|
||||
}
|
||||
|
||||
gc32_t* pool32 = vm->gc.pool32;
|
||||
while (pool32) {
|
||||
allocated += POOL32_SLOTS;
|
||||
used += POOL32_SLOTS - count_bits_1(pool32->bitmap);
|
||||
used += POOL32_SLOTS - popcount(pool32->bitmap);
|
||||
pool32 = pool32->next;
|
||||
}
|
||||
if (slots_used) { *slots_used = used; }
|
||||
|
|
Loading…
Reference in New Issue