fixed print_formatted() to use hcl_outfmtobj() instead of hcl_print().

added 2 new optional callbacks - vmprim.alloc_heap and vmprim.free_heap
This commit is contained in:
hyung-hwan 2018-03-01 14:47:12 +00:00
parent 0b460a3f2a
commit 9094157e28
6 changed files with 277 additions and 201 deletions

View File

@ -321,7 +321,6 @@ void hcl_seterrwithsyserr (hcl_t* hcl, int syserr)
} }
} }
void hcl_getsynerr (hcl_t* hcl, hcl_synerr_t* synerr) void hcl_getsynerr (hcl_t* hcl, hcl_synerr_t* synerr)
{ {
HCL_ASSERT (hcl, hcl->c != HCL_NULL); HCL_ASSERT (hcl, hcl->c != HCL_NULL);
@ -445,7 +444,6 @@ void hcl_assertfailed (hcl_t* hcl, const hcl_bch_t* expr, const hcl_bch_t* file,
hcl_logbfmt (hcl, HCL_LOG_UNTYPED | HCL_LOG_FATAL, "ASSERTION FAILURE: %s at %s:%zu\n", expr, file, line); hcl_logbfmt (hcl, HCL_LOG_UNTYPED | HCL_LOG_FATAL, "ASSERTION FAILURE: %s at %s:%zu\n", expr, file, line);
#if defined(HAVE_BACKTRACE) #if defined(HAVE_BACKTRACE)
btsize = backtrace (btarray, HCL_COUNTOF(btarray)); btsize = backtrace (btarray, HCL_COUNTOF(btarray));
btsyms = backtrace_symbols (btarray, btsize); btsyms = backtrace_symbols (btarray, btsize);

View File

@ -83,6 +83,16 @@ static void fill_bigint_tables (hcl_t* hcl)
} }
} }
static void* alloc_heap (hcl_t* hcl, hcl_oow_t size)
{
return HCL_MMGR_ALLOC(hcl->mmgr, size);
}
static void free_heap (hcl_t* hcl, void* ptr)
{
return HCL_MMGR_FREE(hcl->mmgr, ptr);
}
int hcl_init (hcl_t* hcl, hcl_mmgr_t* mmgr, hcl_oow_t heapsz, const hcl_vmprim_t* vmprim) int hcl_init (hcl_t* hcl, hcl_mmgr_t* mmgr, hcl_oow_t heapsz, const hcl_vmprim_t* vmprim)
{ {
int modtab_inited = 0; int modtab_inited = 0;
@ -97,6 +107,8 @@ int hcl_init (hcl_t* hcl, hcl_mmgr_t* mmgr, hcl_oow_t heapsz, const hcl_vmprim_t
hcl->mmgr = mmgr; hcl->mmgr = mmgr;
hcl->cmgr = hcl_getutf8cmgr(); hcl->cmgr = hcl_getutf8cmgr();
hcl->vmprim = *vmprim; hcl->vmprim = *vmprim;
if (!hcl->vmprim.alloc_heap) hcl->vmprim.alloc_heap = alloc_heap;
if (!hcl->vmprim.free_heap) hcl->vmprim.free_heap = free_heap;
hcl->option.log_mask = ~0u; hcl->option.log_mask = ~0u;
hcl->option.log_maxcapa = HCL_DFL_LOG_MAXCAPA; hcl->option.log_maxcapa = HCL_DFL_LOG_MAXCAPA;
@ -113,19 +125,19 @@ int hcl_init (hcl_t* hcl, hcl_mmgr_t* mmgr, hcl_oow_t heapsz, const hcl_vmprim_t
* routine still function despite some side-effects when * routine still function despite some side-effects when
* reallocation fails */ * reallocation fails */
/* +1 required for consistency with put_oocs and put_ooch in logfmt.c */ /* +1 required for consistency with put_oocs and put_ooch in logfmt.c */
hcl->log.ptr = (hcl_ooch_t*)hcl_allocmem (hcl, (hcl->log.capa + 1) * HCL_SIZEOF(*hcl->log.ptr)); hcl->log.ptr = (hcl_ooch_t*)hcl_allocmem(hcl, (hcl->log.capa + 1) * HCL_SIZEOF(*hcl->log.ptr));
if (!hcl->log.ptr) goto oops; if (!hcl->log.ptr) goto oops;
/*hcl->permheap = hcl_makeheap (hcl, what is the best size???); /*hcl->permheap = hcl_makeheap (hcl, what is the best size???);
if (!hcl->curheap) goto oops; */ if (!hcl->curheap) goto oops; */
hcl->curheap = hcl_makeheap (hcl, heapsz); hcl->curheap = hcl_makeheap(hcl, heapsz);
if (!hcl->curheap) goto oops; if (!hcl->curheap) goto oops;
hcl->newheap = hcl_makeheap (hcl, heapsz); hcl->newheap = hcl_makeheap(hcl, heapsz);
if (!hcl->newheap) goto oops; if (!hcl->newheap) goto oops;
if (hcl_rbt_init (&hcl->modtab, hcl, HCL_SIZEOF(hcl_ooch_t), 1) <= -1) goto oops; if (hcl_rbt_init(&hcl->modtab, hcl, HCL_SIZEOF(hcl_ooch_t), 1) <= -1) goto oops;
modtab_inited = 1; modtab_inited = 1;
hcl_rbt_setstyle (&hcl->modtab, hcl_getrbtstyle(HCL_RBT_STYLE_INLINE_COPIERS)); hcl_rbt_setstyle(&hcl->modtab, hcl_getrbtstyle(HCL_RBT_STYLE_INLINE_COPIERS));
fill_bigint_tables (hcl); fill_bigint_tables (hcl);
@ -241,7 +253,7 @@ void hcl_fini (hcl_t* hcl)
hcl_killheap (hcl, hcl->newheap); hcl_killheap (hcl, hcl->newheap);
hcl_killheap (hcl, hcl->curheap); hcl_killheap (hcl, hcl->curheap);
hcl_killheap (hcl, hcl->permheap); if (hcl->permheap) hcl_killheap (hcl, hcl->permheap);
if (hcl->log.ptr) if (hcl->log.ptr)
{ {

View File

@ -686,6 +686,14 @@ struct hcl_heap_t
/* ========================================================================= /* =========================================================================
* VIRTUAL MACHINE PRIMITIVES * VIRTUAL MACHINE PRIMITIVES
* ========================================================================= */ * ========================================================================= */
typedef void* (*hcl_alloc_heap_t) (hcl_t* hcl, hcl_oow_t size);
typedef void (*hcl_free_heap_t) (hcl_t* hcl, void* ptr);
typedef void (*hcl_log_write_t) (hcl_t* hcl, int mask, const hcl_ooch_t* msg, hcl_oow_t len);
typedef void (*hcl_syserrstrb_t) (hcl_t* hcl, int syserr, hcl_bch_t* buf, hcl_oow_t len);
typedef void (*hcl_syserrstru_t) (hcl_t* hcl, int syserr, hcl_uch_t* buf, hcl_oow_t len);
enum hcl_vmprim_opendl_flag_t enum hcl_vmprim_opendl_flag_t
{ {
HCL_VMPRIM_OPENDL_PFMOD = (1 << 0) HCL_VMPRIM_OPENDL_PFMOD = (1 << 0)
@ -696,27 +704,34 @@ typedef void* (*hcl_vmprim_dlopen_t) (hcl_t* hcl, const hcl_ooch_t* name, int fl
typedef void (*hcl_vmprim_dlclose_t) (hcl_t* hcl, void* handle); typedef void (*hcl_vmprim_dlclose_t) (hcl_t* hcl, void* handle);
typedef void* (*hcl_vmprim_dlgetsym_t) (hcl_t* hcl, void* handle, const hcl_ooch_t* name); typedef void* (*hcl_vmprim_dlgetsym_t) (hcl_t* hcl, void* handle, const hcl_ooch_t* name);
typedef void (*hcl_log_write_t) (hcl_t* hcl, int mask, const hcl_ooch_t* msg, hcl_oow_t len);
typedef void (*hcl_syserrstrb_t) (hcl_t* hcl, int syserr, hcl_bch_t* buf, hcl_oow_t len);
typedef void (*hcl_syserrstru_t) (hcl_t* hcl, int syserr, hcl_uch_t* buf, hcl_oow_t len);
typedef int (*hcl_vmprim_startup_t) (hcl_t* hcl); typedef int (*hcl_vmprim_startup_t) (hcl_t* hcl);
typedef void (*hcl_vmprim_cleanup_t) (hcl_t* hcl); typedef void (*hcl_vmprim_cleanup_t) (hcl_t* hcl);
typedef void (*hcl_vmprim_gettime_t) (hcl_t* hcl, hcl_ntime_t* now); typedef void (*hcl_vmprim_gettime_t) (hcl_t* hcl, hcl_ntime_t* now);
typedef void (*hcl_vmprim_sleep_t) (hcl_t* hcl, const hcl_ntime_t* duration); typedef void (*hcl_vmprim_sleep_t) (hcl_t* hcl, const hcl_ntime_t* duration);
struct hcl_vmprim_t struct hcl_vmprim_t
{ {
hcl_vmprim_dlopen_t dl_open; /* The alloc_heap callback function is called very earlier
hcl_vmprim_dlclose_t dl_close; * before hcl is fully initialized. so few features are availble
hcl_vmprim_dlgetsym_t dl_getsym; * in this callback function. If it's not provided, the default
* implementation is used. */
hcl_alloc_heap_t alloc_heap;
/* If you customize the heap allocator by providing the alloc_heap
* callback, you should implement the heap freer. otherwise the default
* implementation doesn't know how to free the heap allocated by
* the allocator callback. */
hcl_free_heap_t free_heap;
hcl_log_write_t log_write; hcl_log_write_t log_write;
hcl_syserrstrb_t syserrstrb; hcl_syserrstrb_t syserrstrb;
hcl_syserrstru_t syserrstru; hcl_syserrstru_t syserrstru;
hcl_vmprim_dlopen_t dl_open;
hcl_vmprim_dlclose_t dl_close;
hcl_vmprim_dlgetsym_t dl_getsym;
hcl_vmprim_startup_t vm_startup; hcl_vmprim_startup_t vm_startup;
hcl_vmprim_cleanup_t vm_cleanup; hcl_vmprim_cleanup_t vm_cleanup;
hcl_vmprim_gettime_t vm_gettime; hcl_vmprim_gettime_t vm_gettime;

View File

@ -30,7 +30,7 @@ hcl_heap_t* hcl_makeheap (hcl_t* hcl, hcl_oow_t size)
{ {
hcl_heap_t* heap; hcl_heap_t* heap;
heap = (hcl_heap_t*)HCL_MMGR_ALLOC(hcl->mmgr, HCL_SIZEOF(*heap) + size); heap = (hcl_heap_t*)hcl->vmprim.alloc_heap(hcl, HCL_SIZEOF(*heap) + size);
if (!heap) if (!heap)
{ {
hcl_seterrnum (hcl, HCL_ESYSMEM); hcl_seterrnum (hcl, HCL_ESYSMEM);
@ -58,7 +58,7 @@ hcl_heap_t* hcl_makeheap (hcl_t* hcl, hcl_oow_t size)
void hcl_killheap (hcl_t* hcl, hcl_heap_t* heap) void hcl_killheap (hcl_t* hcl, hcl_heap_t* heap)
{ {
HCL_MMGR_FREE (hcl->mmgr, heap); hcl->vmprim.free_heap (hcl, heap);
} }
void* hcl_allocheapmem (hcl_t* hcl, hcl_heap_t* heap, hcl_oow_t size) void* hcl_allocheapmem (hcl_t* hcl, hcl_heap_t* heap, hcl_oow_t size)

View File

@ -771,18 +771,16 @@ static HCL_INLINE int print_formatted (hcl_t* hcl, hcl_ooi_t nargs, hcl_fmtout_t
arg = HCL_STACK_GETARG(hcl, nargs, 0); arg = HCL_STACK_GETARG(hcl, nargs, 0);
if (!HCL_OOP_IS_POINTER(arg) || HCL_OBJ_GET_FLAGS_TYPE(arg) != HCL_OBJ_TYPE_CHAR) if (!HCL_OOP_IS_POINTER(arg) || HCL_OBJ_GET_FLAGS_TYPE(arg) != HCL_OBJ_TYPE_CHAR)
{ {
#if 0
hcl_ooi_t i; hcl_ooi_t i;
/* if the first argument is not a valid formatting string, /* if the first argument is not a valid formatting string,
* print all arguments as objects */ * print all arguments as objects */
if (hcl_print(hcl, arg) <= -1) goto oops; if (hcl_outfmtobj(hcl, data->mask, arg, outbfmt) <= -1) goto oops;
for (i = 1; i < nargs; i++) for (i = 1; i < nargs; i++)
{ {
arg = HCL_STACK_GETARG(hcl, nargs, i); arg = HCL_STACK_GETARG(hcl, nargs, i);
if (hcl_print(hcl, arg) <= -1) goto oops; if (hcl_outfmtobj(hcl, data->mask, arg, outbfmt) <= -1) goto oops;
} }
return 0; return 0;
#endif
} }
fmt = HCL_OBJ_GET_CHAR_SLOT(arg); fmt = HCL_OBJ_GET_CHAR_SLOT(arg);

View File

@ -88,6 +88,7 @@
# include <unistd.h> # include <unistd.h>
# include <fcntl.h> # include <fcntl.h>
# include <sys/mman.h>
#endif #endif
#if !defined(HCL_DEFAULT_PFMODPREFIX) #if !defined(HCL_DEFAULT_PFMODPREFIX)
@ -146,14 +147,16 @@ struct xtn_t
/* ========================================================================= */ /* ========================================================================= */
#define MB_1 (256UL*1024*1024)
static void* sys_alloc (hcl_mmgr_t* mmgr, hcl_oow_t size) static void* sys_alloc (hcl_mmgr_t* mmgr, hcl_oow_t size)
{ {
return malloc (size); return malloc(size);
} }
static void* sys_realloc (hcl_mmgr_t* mmgr, void* ptr, hcl_oow_t size) static void* sys_realloc (hcl_mmgr_t* mmgr, void* ptr, hcl_oow_t size)
{ {
return realloc (ptr, size); return realloc(ptr, size);
} }
static void sys_free (hcl_mmgr_t* mmgr, void* ptr) static void sys_free (hcl_mmgr_t* mmgr, void* ptr)
@ -378,7 +381,7 @@ static HCL_INLINE hcl_ooi_t close_output (hcl_t* hcl, hcl_iooutarg_t* arg)
fp = (FILE*)arg->handle; fp = (FILE*)arg->handle;
HCL_ASSERT (hcl, fp != HCL_NULL); HCL_ASSERT (hcl, fp != HCL_NULL);
fclose (fp); if (fp != stdout) fclose (fp);
arg->handle = HCL_NULL; arg->handle = HCL_NULL;
return 0; return 0;
} }
@ -395,18 +398,18 @@ static HCL_INLINE hcl_ooi_t write_output (hcl_t* hcl, hcl_iooutarg_t* arg)
do do
{ {
#if defined(HCL_OOCH_IS_UCH) #if defined(HCL_OOCH_IS_UCH)
bcslen = HCL_COUNTOF(bcsbuf); bcslen = HCL_COUNTOF(bcsbuf);
ucslen = arg->len - donelen; ucslen = arg->len - donelen;
x = hcl_convootobchars (hcl, &arg->ptr[donelen], &ucslen, bcsbuf, &bcslen); x = hcl_convootobchars (hcl, &arg->ptr[donelen], &ucslen, bcsbuf, &bcslen);
if (x <= -1 && ucslen <= 0) return -1; if (x <= -1 && ucslen <= 0) return -1;
#else #else
bcslen = HCL_COUNTOF(bcsbuf); bcslen = HCL_COUNTOF(bcsbuf);
ucslen = arg->len - donelen; ucslen = arg->len - donelen;
if (ucslen > bcslen) ucslen = bcslen; if (ucslen > bcslen) ucslen = bcslen;
else if (ucslen < bcslen) bcslen = ucslen; else if (ucslen < bcslen) bcslen = ucslen;
hcl_copybchars (bcsbuf, &arg->ptr[donelen], bcslen); hcl_copybchars (bcsbuf, &arg->ptr[donelen], bcslen);
#endif #endif
if (fwrite (bcsbuf, HCL_SIZEOF(bcsbuf[0]), bcslen, (FILE*)arg->handle) < bcslen) if (fwrite (bcsbuf, HCL_SIZEOF(bcsbuf[0]), bcslen, (FILE*)arg->handle) < bcslen)
{ {
@ -442,6 +445,212 @@ static hcl_ooi_t print_handler (hcl_t* hcl, hcl_iocmd_t cmd, void* arg)
/* ========================================================================= */ /* ========================================================================= */
static void* alloc_heap (hcl_t* hcl, hcl_oow_t size)
{
/* It's called when HCL creates a GC heap.
* The heap is large in size. I can use a different memory allocation
* function instead of an ordinary malloc */
hcl_oow_t* ptr;
int flags;
hcl_oow_t actual_size;
flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB;
#if defined(MAP_UNINITIALIZED)
flags |= MAP_UNINITIALIZED;
#endif
actual_size = HCL_SIZEOF(hcl_oow_t) + size;
actual_size = HCL_ALIGN_POW2(actual_size, 2 * 1024 * 1024);
ptr = (hcl_oow_t*)mmap(NULL, actual_size, PROT_READ | PROT_WRITE, flags, -1, 0);
if (ptr == MAP_FAILED)
{
flags &= ~MAP_HUGETLB;
ptr = (hcl_oow_t*)mmap(NULL, actual_size, PROT_READ | PROT_WRITE, flags, -1, 0);
if (ptr == MAP_FAILED) return HCL_NULL;
}
*ptr = size;
return (void*)(ptr + 1);
/*return HCL_MMGR_ALLOC(hcl->mmgr, size);*/
}
static void free_heap (hcl_t* hcl, void* ptr)
{
hcl_oow_t* actual_ptr;
actual_ptr = (hcl_oow_t*)ptr - 1;
munmap (actual_ptr, *actual_ptr);
/*return HCL_MMGR_FREE(hcl->mmgr, ptr);*/
}
static int write_all (int fd, const char* ptr, hcl_oow_t len)
{
while (len > 0)
{
hcl_ooi_t wr;
wr = write (1, ptr, len);
if (wr <= -1)
{
#if defined(EAGAIN) && defined(EWOULDBLOCK) && (EAGAIN == EWOULDBLOCK)
if (errno == EAGAIN) continue;
#else
# if defined(EAGAIN)
if (errno == EAGAIN) continue;
#elif defined(EWOULDBLOCK)
if (errno == EWOULDBLOCK) continue;
#endif
#endif
#if defined(EINTR)
/* TODO: would this interfere with non-blocking nature of this VM? */
if (errno == EINTR) continue;
#endif
return -1;
}
ptr += wr;
len -= wr;
}
return 0;
}
static void log_write (hcl_t* hcl, int mask, const hcl_ooch_t* msg, hcl_oow_t len)
{
#if defined(_WIN32)
# error NOT IMPLEMENTED
#elif defined(macintosh)
# error NOT IMPLEMENTED
#else
hcl_bch_t buf[256];
hcl_oow_t ucslen, bcslen, msgidx;
int n;
xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);
int logfd;
if (mask & HCL_LOG_STDERR)
{
/* the messages that go to STDERR don't get masked out */
logfd = 2;
}
else
{
if (!(xtn->logmask & mask & ~HCL_LOG_ALL_LEVELS)) return; /* check log types */
if (!(xtn->logmask & mask & ~HCL_LOG_ALL_TYPES)) return; /* check log levels */
if (mask & HCL_LOG_STDOUT) logfd = 1;
else
{
logfd = xtn->logfd;
if (logfd <= -1) return;
}
}
/* TODO: beautify the log message.
* do classification based on mask. */
if (!(mask & (HCL_LOG_STDOUT | HCL_LOG_STDERR)))
{
time_t now;
char ts[32];
size_t tslen;
struct tm tm, *tmp;
now = time(NULL);
#if defined(__DOS__)
tmp = localtime (&now);
tslen = strftime (ts, sizeof(ts), "%Y-%m-%d %H:%M:%S ", tmp); /* no timezone info */
if (tslen == 0)
{
strcpy (ts, "0000-00-00 00:00:00");
tslen = 19;
}
#else
tmp = localtime_r (&now, &tm);
#if defined(HAVE_STRFTIME_SMALL_Z)
tslen = strftime (ts, sizeof(ts), "%Y-%m-%d %H:%M:%S %z ", tmp);
#else
tslen = strftime (ts, sizeof(ts), "%Y-%m-%d %H:%M:%S %Z ", tmp);
#endif
if (tslen == 0)
{
strcpy (ts, "0000-00-00 00:00:00 +0000");
tslen = 25;
}
#endif
write_all (logfd, ts, tslen);
}
if (xtn->logfd_istty)
{
if (mask & HCL_LOG_FATAL) write_all (logfd, "\x1B[1;31m", 7);
else if (mask & HCL_LOG_ERROR) write_all (logfd, "\x1B[1;32m", 7);
else if (mask & HCL_LOG_WARN) write_all (logfd, "\x1B[1;33m", 7);
}
#if defined(HCL_OOCH_IS_UCH)
msgidx = 0;
while (len > 0)
{
ucslen = len;
bcslen = HCL_COUNTOF(buf);
n = hcl_convootobchars (hcl, &msg[msgidx], &ucslen, buf, &bcslen);
if (n == 0 || n == -2)
{
/* n = 0:
* converted all successfully
* n == -2:
* buffer not sufficient. not all got converted yet.
* write what have been converted this round. */
HCL_ASSERT (hcl, ucslen > 0); /* if this fails, the buffer size must be increased */
/* attempt to write all converted characters */
if (write_all (logfd, buf, bcslen) <= -1) break;
if (n == 0) break;
else
{
msgidx += ucslen;
len -= ucslen;
}
}
else if (n <= -1)
{
/* conversion error */
break;
}
}
#else
write_all (logfd, msg, len);
#endif
if (xtn->logfd_istty)
{
if (mask & (HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN)) write_all (logfd, "\x1B[0m", 4);
}
#endif
}
static void syserrstrb (hcl_t* hcl, int syserr, hcl_bch_t* buf, hcl_oow_t len)
{
#if defined(HAVE_STRERROR_R)
strerror_r (syserr, buf, len);
#else
/* this is not thread safe */
hcl_copybcstr (buf, len, strerror(syserr));
#endif
}
/* ========================================================================= */
static void* dl_open (hcl_t* hcl, const hcl_ooch_t* name, int flags) static void* dl_open (hcl_t* hcl, const hcl_ooch_t* name, int flags)
{ {
#if defined(USE_LTDL) || defined(USE_DLFCN) #if defined(USE_LTDL) || defined(USE_DLFCN)
@ -671,172 +880,7 @@ static void* dl_getsym (hcl_t* hcl, void* handle, const hcl_ooch_t* name)
#endif #endif
} }
static int write_all (int fd, const char* ptr, hcl_oow_t len) /* ========================================================================= */
{
while (len > 0)
{
hcl_ooi_t wr;
wr = write (1, ptr, len);
if (wr <= -1)
{
#if defined(EAGAIN) && defined(EWOULDBLOCK) && (EAGAIN == EWOULDBLOCK)
if (errno == EAGAIN) continue;
#else
# if defined(EAGAIN)
if (errno == EAGAIN) continue;
#elif defined(EWOULDBLOCK)
if (errno == EWOULDBLOCK) continue;
#endif
#endif
#if defined(EINTR)
/* TODO: would this interfere with non-blocking nature of this VM? */
if (errno == EINTR) continue;
#endif
return -1;
}
ptr += wr;
len -= wr;
}
return 0;
}
static void log_write (hcl_t* hcl, int mask, const hcl_ooch_t* msg, hcl_oow_t len)
{
#if defined(_WIN32)
# error NOT IMPLEMENTED
#elif defined(macintosh)
# error NOT IMPLEMENTED
#else
hcl_bch_t buf[256];
hcl_oow_t ucslen, bcslen, msgidx;
int n;
xtn_t* xtn = (xtn_t*)hcl_getxtn(hcl);
int logfd;
if (mask & HCL_LOG_STDERR)
{
/* the messages that go to STDERR don't get masked out */
logfd = 2;
}
else
{
if (!(xtn->logmask & mask & ~HCL_LOG_ALL_LEVELS)) return; /* check log types */
if (!(xtn->logmask & mask & ~HCL_LOG_ALL_TYPES)) return; /* check log levels */
if (mask & HCL_LOG_STDOUT) logfd = 1;
else
{
logfd = xtn->logfd;
if (logfd <= -1) return;
}
}
/* TODO: beautify the log message.
* do classification based on mask. */
if (!(mask & (HCL_LOG_STDOUT | HCL_LOG_STDERR)))
{
time_t now;
char ts[32];
size_t tslen;
struct tm tm, *tmp;
now = time(NULL);
#if defined(__DOS__)
tmp = localtime (&now);
tslen = strftime (ts, sizeof(ts), "%Y-%m-%d %H:%M:%S ", tmp); /* no timezone info */
if (tslen == 0)
{
strcpy (ts, "0000-00-00 00:00:00");
tslen = 19;
}
#else
tmp = localtime_r (&now, &tm);
#if defined(HAVE_STRFTIME_SMALL_Z)
tslen = strftime (ts, sizeof(ts), "%Y-%m-%d %H:%M:%S %z ", tmp);
#else
tslen = strftime (ts, sizeof(ts), "%Y-%m-%d %H:%M:%S %Z ", tmp);
#endif
if (tslen == 0)
{
strcpy (ts, "0000-00-00 00:00:00 +0000");
tslen = 25;
}
#endif
write_all (logfd, ts, tslen);
}
if (xtn->logfd_istty)
{
if (mask & HCL_LOG_FATAL) write_all (logfd, "\x1B[1;31m", 7);
else if (mask & HCL_LOG_ERROR) write_all (logfd, "\x1B[1;32m", 7);
else if (mask & HCL_LOG_WARN) write_all (logfd, "\x1B[1;33m", 7);
}
#if defined(HCL_OOCH_IS_UCH)
msgidx = 0;
while (len > 0)
{
ucslen = len;
bcslen = HCL_COUNTOF(buf);
n = hcl_convootobchars (hcl, &msg[msgidx], &ucslen, buf, &bcslen);
if (n == 0 || n == -2)
{
/* n = 0:
* converted all successfully
* n == -2:
* buffer not sufficient. not all got converted yet.
* write what have been converted this round. */
HCL_ASSERT (hcl, ucslen > 0); /* if this fails, the buffer size must be increased */
/* attempt to write all converted characters */
if (write_all (logfd, buf, bcslen) <= -1) break;
if (n == 0) break;
else
{
msgidx += ucslen;
len -= ucslen;
}
}
else if (n <= -1)
{
/* conversion error */
break;
}
}
#else
write_all (logfd, msg, len);
#endif
if (xtn->logfd_istty)
{
if (mask & (HCL_LOG_FATAL | HCL_LOG_ERROR | HCL_LOG_WARN)) write_all (logfd, "\x1B[0m", 4);
}
#endif
}
static void syserrstrb (hcl_t* hcl, int syserr, hcl_bch_t* buf, hcl_oow_t len)
{
#if defined(HAVE_STRERROR_R)
strerror_r (syserr, buf, len);
#else
/* this is not thread safe */
hcl_copybcstr (buf, len, strerror(syserr));
#endif
}
static int vm_startup (hcl_t* hcl) static int vm_startup (hcl_t* hcl)
{ {
@ -925,7 +969,6 @@ static int vm_startup (hcl_t* hcl)
xtn->iothr_up = 0; xtn->iothr_up = 0;
/*pthread_create (&xtn->iothr, HCL_NULL, iothr_main, hcl);*/ /*pthread_create (&xtn->iothr, HCL_NULL, iothr_main, hcl);*/
#endif /* USE_THREAD */ #endif /* USE_THREAD */
xtn->vm_running = 1; xtn->vm_running = 1;
@ -1435,6 +1478,7 @@ int main (int argc, char* argv[])
{ {
{ ":log", 'l' }, { ":log", 'l' },
{ ":memsize", 'm' }, { ":memsize", 'm' },
{ "large-pages", '\0' },
#if defined(HCL_BUILD_DEBUG) #if defined(HCL_BUILD_DEBUG)
{ ":debug", '\0' }, /* NOTE: there is no short option for --debug */ { ":debug", '\0' }, /* NOTE: there is no short option for --debug */
#endif #endif
@ -1448,6 +1492,7 @@ int main (int argc, char* argv[])
const char* logopt = HCL_NULL; const char* logopt = HCL_NULL;
hcl_oow_t memsize = MIN_MEMSIZE; hcl_oow_t memsize = MIN_MEMSIZE;
int large_pages = 0;
#if defined(HCL_BUILD_DEBUG) #if defined(HCL_BUILD_DEBUG)
const char* dbgopt = HCL_NULL; const char* dbgopt = HCL_NULL;
@ -1477,9 +1522,13 @@ int main (int argc, char* argv[])
break; break;
case '\0': case '\0':
if (hcl_compbcstr(opt.lngopt, "large-pages") == 0)
{
large_pages = 1;
break;
}
#if defined(HCL_BUILD_DEBUG) #if defined(HCL_BUILD_DEBUG)
if (hcl_compbcstr(opt.lngopt, "debug") == 0) else if (hcl_compbcstr(opt.lngopt, "debug") == 0)
{ {
dbgopt = opt.arg; dbgopt = opt.arg;
break; break;
@ -1504,19 +1553,23 @@ int main (int argc, char* argv[])
if (opt.ind >= argc) goto print_usage; if (opt.ind >= argc) goto print_usage;
#endif #endif
memset (&vmprim, 0, HCL_SIZEOF(vmprim)); memset (&vmprim, 0, HCL_SIZEOF(vmprim));
if (large_pages)
{
vmprim.alloc_heap = alloc_heap;
vmprim.free_heap = free_heap;
}
vmprim.log_write = log_write;
vmprim.syserrstrb = syserrstrb;
vmprim.dl_open = dl_open; vmprim.dl_open = dl_open;
vmprim.dl_close = dl_close; vmprim.dl_close = dl_close;
vmprim.dl_getsym = dl_getsym; vmprim.dl_getsym = dl_getsym;
vmprim.log_write = log_write;
vmprim.syserrstrb = syserrstrb;
vmprim.vm_startup = vm_startup; vmprim.vm_startup = vm_startup;
vmprim.vm_cleanup = vm_cleanup; vmprim.vm_cleanup = vm_cleanup;
vmprim.vm_gettime = vm_gettime; vmprim.vm_gettime = vm_gettime;
vmprim.vm_sleep = vm_sleep; vmprim.vm_sleep = vm_sleep;
hcl = hcl_open (&sys_mmgr, HCL_SIZEOF(xtn_t), 2048000lu, &vmprim, HCL_NULL); hcl = hcl_open (&sys_mmgr, HCL_SIZEOF(xtn_t), memsize, &vmprim, HCL_NULL);
if (!hcl) if (!hcl)
{ {
printf ("cannot open hcl\n"); printf ("cannot open hcl\n");