diff --git a/moo/lib/heap.c b/moo/lib/heap.c index 30ab517..356f153 100644 --- a/moo/lib/heap.c +++ b/moo/lib/heap.c @@ -30,7 +30,7 @@ moo_heap_t* moo_makeheap (moo_t* moo, moo_oow_t size) { moo_heap_t* heap; - heap = (moo_heap_t*)MOO_MMGR_ALLOC(moo->mmgr, MOO_SIZEOF(*heap) + size); + heap = (moo_heap_t*)moo->vmprim.alloc_heap(moo, MOO_SIZEOF(*heap) + size); if (!heap) { moo_seterrnum (moo, MOO_ESYSMEM); @@ -58,7 +58,7 @@ moo_heap_t* moo_makeheap (moo_t* moo, moo_oow_t size) void moo_killheap (moo_t* moo, moo_heap_t* heap) { - MOO_MMGR_FREE (moo->mmgr, heap); + moo->vmprim.free_heap (moo, heap); } void* moo_allocheapmem (moo_t* moo, moo_heap_t* heap, moo_oow_t size) diff --git a/moo/lib/main.c b/moo/lib/main.c index d33c899..a9a6bf8 100644 --- a/moo/lib/main.c +++ b/moo/lib/main.c @@ -478,6 +478,195 @@ static moo_ooi_t input_handler (moo_t* moo, moo_iocmd_t cmd, moo_ioarg_t* arg) return -1; } } + +/* ========================================================================= */ + +static void* alloc_heap (moo_t* moo, moo_oow_t size) +{ + return MOO_MMGR_ALLOC(moo->mmgr, size); +} + +static void free_heap (moo_t* moo, void* ptr) +{ + return MOO_MMGR_FREE(moo->mmgr, ptr); +} + +#if defined(_WIN32) + /* nothing to do */ + +#elif defined(macintosh) + /* nothing to do */ + +#else +static int write_all (int fd, const char* ptr, moo_oow_t len) +{ + while (len > 0) + { + moo_ooi_t wr; + + wr = write (fd, ptr, len); + + if (wr <= -1) + { + #if defined(EAGAIN) && defined(EWOULDBLOCK) && (EAGAIN == EWOULDBLOCK) + /* TODO: push it to internal buffers? before writing data just converted, need to write buffered data first. */ + if (errno == EAGAIN) continue; + #else + + #if defined(EAGAIN) + if (errno == EAGAIN) continue; + #endif + #if 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; +} +#endif + +static void log_write (moo_t* moo, moo_oow_t mask, const moo_ooch_t* msg, moo_oow_t len) +{ +#if defined(_WIN32) +# error NOT IMPLEMENTED + +#elif defined(macintosh) +# error NOT IMPLEMENTED +#else + moo_bch_t buf[256]; + moo_oow_t ucslen, bcslen, msgidx; + int n; + + xtn_t* xtn = moo_getxtn(moo); + int logfd; + + if (mask & MOO_LOG_STDERR) + { + /* the messages that go to STDERR don't get masked out */ + logfd = 2; + } + else + { + if (!(xtn->logmask & mask & ~MOO_LOG_ALL_LEVELS)) return; /* check log types */ + if (!(xtn->logmask & mask & ~MOO_LOG_ALL_TYPES)) return; /* check log levels */ + + if (mask & MOO_LOG_STDOUT) logfd = 1; + else + { + logfd = xtn->logfd; + if (logfd <= -1) return; + } + } + +/* TODO: beautify the log message. + * do classification based on mask. */ + if (!(mask & (MOO_LOG_STDOUT | MOO_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 & MOO_LOG_FATAL) write_all (logfd, "\x1B[1;31m", 7); + else if (mask & MOO_LOG_ERROR) write_all (logfd, "\x1B[1;32m", 7); + else if (mask & MOO_LOG_WARN) write_all (logfd, "\x1B[1;33m", 7); + } + +#if defined(MOO_OOCH_IS_UCH) + msgidx = 0; + while (len > 0) + { + ucslen = len; + bcslen = MOO_COUNTOF(buf); + + n = moo_convootobchars(moo, &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. */ + + MOO_ASSERT (moo, 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 & (MOO_LOG_FATAL | MOO_LOG_ERROR | MOO_LOG_WARN)) write_all (logfd, "\x1B[0m", 4); + } + +#endif +} + +static void syserrstrb (moo_t* moo, int syserr, moo_bch_t* buf, moo_oow_t len) +{ +#if defined(HAVE_STRERROR_R) + strerror_r (syserr, buf, len); +#else + /* this is not thread safe */ + moo_copybcstr (buf, len, strerror(syserr)); +#endif +} + /* ========================================================================= */ static void* dl_open (moo_t* moo, const moo_ooch_t* name, int flags) @@ -706,184 +895,6 @@ static void* dl_getsym (moo_t* moo, void* handle, const moo_ooch_t* name) #endif } -/* ========================================================================= */ - -#if defined(_WIN32) - /* nothing to do */ - -#elif defined(macintosh) - /* nothing to do */ - -#else -static int write_all (int fd, const char* ptr, moo_oow_t len) -{ - while (len > 0) - { - moo_ooi_t wr; - - wr = write (fd, ptr, len); - - if (wr <= -1) - { - #if defined(EAGAIN) && defined(EWOULDBLOCK) && (EAGAIN == EWOULDBLOCK) - /* TODO: push it to internal buffers? before writing data just converted, need to write buffered data first. */ - if (errno == EAGAIN) continue; - #else - - #if defined(EAGAIN) - if (errno == EAGAIN) continue; - #endif - #if 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; -} -#endif - -static void log_write (moo_t* moo, moo_oow_t mask, const moo_ooch_t* msg, moo_oow_t len) -{ -#if defined(_WIN32) -# error NOT IMPLEMENTED - -#elif defined(macintosh) -# error NOT IMPLEMENTED -#else - moo_bch_t buf[256]; - moo_oow_t ucslen, bcslen, msgidx; - int n; - - xtn_t* xtn = moo_getxtn(moo); - int logfd; - - if (mask & MOO_LOG_STDERR) - { - /* the messages that go to STDERR don't get masked out */ - logfd = 2; - } - else - { - if (!(xtn->logmask & mask & ~MOO_LOG_ALL_LEVELS)) return; /* check log types */ - if (!(xtn->logmask & mask & ~MOO_LOG_ALL_TYPES)) return; /* check log levels */ - - if (mask & MOO_LOG_STDOUT) logfd = 1; - else - { - logfd = xtn->logfd; - if (logfd <= -1) return; - } - } - -/* TODO: beautify the log message. - * do classification based on mask. */ - if (!(mask & (MOO_LOG_STDOUT | MOO_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 & MOO_LOG_FATAL) write_all (logfd, "\x1B[1;31m", 7); - else if (mask & MOO_LOG_ERROR) write_all (logfd, "\x1B[1;32m", 7); - else if (mask & MOO_LOG_WARN) write_all (logfd, "\x1B[1;33m", 7); - } - -#if defined(MOO_OOCH_IS_UCH) - msgidx = 0; - while (len > 0) - { - ucslen = len; - bcslen = MOO_COUNTOF(buf); - - n = moo_convootobchars(moo, &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. */ - - MOO_ASSERT (moo, 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 & (MOO_LOG_FATAL | MOO_LOG_ERROR | MOO_LOG_WARN)) write_all (logfd, "\x1B[0m", 4); - } - -#endif -} - -static void syserrstrb (moo_t* moo, int syserr, moo_bch_t* buf, moo_oow_t len) -{ -#if defined(HAVE_STRERROR_R) - strerror_r (syserr, buf, len); -#else - /* this is not thread safe */ - moo_copybcstr (buf, len, strerror(syserr)); -#endif -} - /* ========================================================================= */ static int _add_poll_fd (moo_t* moo, int fd, int event_mask) { @@ -2287,11 +2298,13 @@ int main (int argc, char* argv[]) #endif memset (&vmprim, 0, MOO_SIZEOF(vmprim)); + 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_close = dl_close; vmprim.dl_getsym = dl_getsym; - vmprim.log_write = log_write; - vmprim.syserrstrb = syserrstrb; vmprim.vm_startup = vm_startup; vmprim.vm_cleanup = vm_cleanup; vmprim.vm_gettime = vm_gettime; diff --git a/moo/lib/moo.c b/moo/lib/moo.c index 02af39e..d2e7f89 100644 --- a/moo/lib/moo.c +++ b/moo/lib/moo.c @@ -82,6 +82,16 @@ static void fill_bigint_tables (moo_t* moo) } } +static void* alloc_heap (moo_t* moo, moo_oow_t size) +{ + return MOO_MMGR_ALLOC(moo->mmgr, size); +} + +static void free_heap (moo_t* moo, void* ptr) +{ + return MOO_MMGR_FREE(moo->mmgr, ptr); +} + int moo_init (moo_t* moo, moo_mmgr_t* mmgr, moo_oow_t heapsz, const moo_vmprim_t* vmprim) { int modtab_inited = 0; @@ -96,6 +106,8 @@ int moo_init (moo_t* moo, moo_mmgr_t* mmgr, moo_oow_t heapsz, const moo_vmprim_t moo->mmgr = mmgr; moo->cmgr = moo_getutf8cmgr(); moo->vmprim = *vmprim; + if (!moo->vmprim.alloc_heap) moo->vmprim.alloc_heap = alloc_heap; + if (!moo->vmprim.free_heap) moo->vmprim.free_heap = free_heap; moo->option.log_mask = ~0u; moo->option.log_maxcapa = MOO_DFL_LOG_MAXCAPA; @@ -238,7 +250,7 @@ void moo_fini (moo_t* moo) moo_killheap (moo, moo->newheap); moo_killheap (moo, moo->curheap); - moo_killheap (moo, moo->permheap); + if (moo->permheap) moo_killheap (moo, moo->permheap); for (i = 0; i < MOO_COUNTOF(moo->sbuf); i++) { diff --git a/moo/lib/moo.h b/moo/lib/moo.h index 712c18a..6b55c83 100644 --- a/moo/lib/moo.h +++ b/moo/lib/moo.h @@ -917,6 +917,14 @@ struct moo_heap_t /* ========================================================================= * VIRTUAL MACHINE PRIMITIVES * ========================================================================= */ + +typedef void* (*moo_alloc_heap_t) (moo_t* moo, moo_oow_t size); +typedef void (*moo_free_heap_t) (moo_t* moo, void* ptr); + +typedef void (*moo_log_write_t) (moo_t* moo, moo_oow_t mask, const moo_ooch_t* msg, moo_oow_t len); +typedef void (*moo_syserrstrb_t) (moo_t* moo, int syserr, moo_bch_t* buf, moo_oow_t len); +typedef void (*moo_syserrstru_t) (moo_t* moo, int syserr, moo_uch_t* buf, moo_oow_t len); + enum moo_vmprim_opendl_flag_t { MOO_VMPRIM_OPENDL_PFMOD = (1 << 0) @@ -927,10 +935,6 @@ typedef void* (*moo_vmprim_dlopen_t) (moo_t* moo, const moo_ooch_t* name, int fl typedef void (*moo_vmprim_dlclose_t) (moo_t* moo, void* handle); typedef void* (*moo_vmprimt_dlgetsym_t) (moo_t* moo, void* handle, const moo_ooch_t* name); -typedef void (*moo_log_write_t) (moo_t* moo, moo_oow_t mask, const moo_ooch_t* msg, moo_oow_t len); -typedef void (*moo_syserrstrb_t) (moo_t* moo, int syserr, moo_bch_t* buf, moo_oow_t len); -typedef void (*moo_syserrstru_t) (moo_t* moo, int syserr, moo_uch_t* buf, moo_oow_t len); - typedef int (*moo_vmprim_startup_t) (moo_t* moo); typedef void (*moo_vmprim_cleanup_t) (moo_t* moo); typedef void (*moo_vmprim_gettime_t) (moo_t* moo, moo_ntime_t* now); @@ -971,13 +975,17 @@ typedef void (*moo_vmprim_sleep_t) ( struct moo_vmprim_t { - moo_vmprim_dlopen_t dl_open; - moo_vmprim_dlclose_t dl_close; - moo_vmprimt_dlgetsym_t dl_getsym; + moo_alloc_heap_t alloc_heap; + moo_free_heap_t free_heap; + moo_log_write_t log_write; moo_syserrstrb_t syserrstrb; moo_syserrstru_t syserrstru; + moo_vmprim_dlopen_t dl_open; + moo_vmprim_dlclose_t dl_close; + moo_vmprimt_dlgetsym_t dl_getsym; + moo_vmprim_startup_t vm_startup; moo_vmprim_cleanup_t vm_cleanup; moo_vmprim_gettime_t vm_gettime;