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:
		| @ -321,7 +321,6 @@ void hcl_seterrwithsyserr (hcl_t* hcl, int syserr) | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| void hcl_getsynerr (hcl_t* hcl, hcl_synerr_t* synerr) | ||||
| { | ||||
| 	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); | ||||
|  | ||||
|  | ||||
| #if defined(HAVE_BACKTRACE) | ||||
| 	btsize = backtrace (btarray, HCL_COUNTOF(btarray)); | ||||
| 	btsyms = backtrace_symbols (btarray, btsize); | ||||
|  | ||||
| @ -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 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->cmgr = hcl_getutf8cmgr(); | ||||
| 	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_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 | ||||
| 	 * reallocation fails */ | ||||
| 	/* +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; | ||||
|  | ||||
| 	/*hcl->permheap = hcl_makeheap (hcl, what is the best size???); | ||||
| 	if (!hcl->curheap) goto oops; */ | ||||
| 	hcl->curheap = hcl_makeheap (hcl, heapsz); | ||||
| 	hcl->curheap = hcl_makeheap(hcl, heapsz); | ||||
| 	if (!hcl->curheap) goto oops; | ||||
| 	hcl->newheap = hcl_makeheap (hcl, heapsz); | ||||
| 	hcl->newheap = hcl_makeheap(hcl, heapsz); | ||||
| 	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; | ||||
| 	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); | ||||
|  | ||||
| @ -241,7 +253,7 @@ void hcl_fini (hcl_t* hcl) | ||||
|  | ||||
| 	hcl_killheap (hcl, hcl->newheap); | ||||
| 	hcl_killheap (hcl, hcl->curheap); | ||||
| 	hcl_killheap (hcl, hcl->permheap); | ||||
| 	if (hcl->permheap) hcl_killheap (hcl, hcl->permheap); | ||||
|  | ||||
| 	if (hcl->log.ptr)  | ||||
| 	{ | ||||
|  | ||||
| @ -686,6 +686,14 @@ struct hcl_heap_t | ||||
| /* ========================================================================= | ||||
|  * 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 | ||||
| { | ||||
| 	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_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 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_sleep_t) (hcl_t* hcl, const hcl_ntime_t* duration); | ||||
|  | ||||
| struct hcl_vmprim_t | ||||
| { | ||||
| 	hcl_vmprim_dlopen_t   dl_open; | ||||
| 	hcl_vmprim_dlclose_t  dl_close; | ||||
| 	hcl_vmprim_dlgetsym_t dl_getsym; | ||||
| 	/* The alloc_heap callback function is called very earlier | ||||
| 	 * before hcl is fully initialized. so few features are availble | ||||
| 	 * 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_syserrstrb_t      syserrstrb; | ||||
| 	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_cleanup_t  vm_cleanup; | ||||
| 	hcl_vmprim_gettime_t  vm_gettime; | ||||
|  | ||||
| @ -30,7 +30,7 @@ hcl_heap_t* hcl_makeheap (hcl_t* hcl, hcl_oow_t size) | ||||
| { | ||||
| 	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) | ||||
| 	{ | ||||
| 		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) | ||||
| { | ||||
| 	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) | ||||
|  | ||||
| @ -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); | ||||
| 	if (!HCL_OOP_IS_POINTER(arg) || HCL_OBJ_GET_FLAGS_TYPE(arg) != HCL_OBJ_TYPE_CHAR) | ||||
| 	{ | ||||
| #if 0 | ||||
| 		hcl_ooi_t i; | ||||
| 		/* if the first argument is not a valid formatting string,  | ||||
| 		 * 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++) | ||||
| 		{ | ||||
| 			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; | ||||
| #endif | ||||
| 	} | ||||
|  | ||||
| 	fmt = HCL_OBJ_GET_CHAR_SLOT(arg); | ||||
|  | ||||
							
								
								
									
										411
									
								
								hcl/lib/main.c
									
									
									
									
									
								
							
							
						
						
									
										411
									
								
								hcl/lib/main.c
									
									
									
									
									
								
							| @ -88,6 +88,7 @@ | ||||
| #	include <unistd.h> | ||||
| #	include <fcntl.h> | ||||
|  | ||||
| #	include <sys/mman.h> | ||||
| #endif | ||||
|  | ||||
| #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) | ||||
| { | ||||
| 	return malloc (size); | ||||
| 	return malloc(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) | ||||
| @ -378,7 +381,7 @@ static HCL_INLINE hcl_ooi_t close_output (hcl_t* hcl, hcl_iooutarg_t* arg) | ||||
| 	fp = (FILE*)arg->handle; | ||||
| 	HCL_ASSERT (hcl, fp != HCL_NULL); | ||||
|  | ||||
| 	fclose (fp); | ||||
| 	if (fp != stdout) fclose (fp); | ||||
| 	arg->handle = HCL_NULL; | ||||
| 	return 0; | ||||
| } | ||||
| @ -395,18 +398,18 @@ static HCL_INLINE hcl_ooi_t write_output (hcl_t* hcl, hcl_iooutarg_t* arg) | ||||
|  | ||||
| 	do  | ||||
| 	{ | ||||
| #if defined(HCL_OOCH_IS_UCH) | ||||
| 	#if defined(HCL_OOCH_IS_UCH) | ||||
| 		bcslen = HCL_COUNTOF(bcsbuf); | ||||
| 		ucslen = arg->len - donelen; | ||||
| 		x = hcl_convootobchars (hcl, &arg->ptr[donelen], &ucslen, bcsbuf, &bcslen); | ||||
| 		if (x <= -1 && ucslen <= 0) return -1; | ||||
| #else | ||||
| 	#else | ||||
| 		bcslen = HCL_COUNTOF(bcsbuf); | ||||
| 		ucslen = arg->len - donelen; | ||||
| 		if (ucslen > bcslen) ucslen = bcslen; | ||||
| 		else if (ucslen < bcslen) bcslen = ucslen; | ||||
| 		hcl_copybchars (bcsbuf, &arg->ptr[donelen], bcslen); | ||||
| #endif | ||||
| 	#endif | ||||
|  | ||||
| 		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) | ||||
| { | ||||
| #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 | ||||
| } | ||||
|  | ||||
| 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) | ||||
| { | ||||
| @ -925,7 +969,6 @@ static int vm_startup (hcl_t* hcl) | ||||
| 	xtn->iothr_up = 0; | ||||
| 	/*pthread_create (&xtn->iothr, HCL_NULL, iothr_main, hcl);*/ | ||||
|  | ||||
| 	 | ||||
| #endif /* USE_THREAD */ | ||||
|  | ||||
| 	xtn->vm_running = 1; | ||||
| @ -1435,6 +1478,7 @@ int main (int argc, char* argv[]) | ||||
| 	{ | ||||
| 		{ ":log",         'l' }, | ||||
| 		{ ":memsize",     'm' }, | ||||
| 		{ "large-pages",  '\0' }, | ||||
| #if defined(HCL_BUILD_DEBUG) | ||||
| 		{ ":debug",       '\0' }, /* NOTE: there is no short option for --debug */ | ||||
| #endif | ||||
| @ -1448,6 +1492,7 @@ int main (int argc, char* argv[]) | ||||
|  | ||||
| 	const char* logopt = HCL_NULL; | ||||
| 	hcl_oow_t memsize = MIN_MEMSIZE; | ||||
| 	int large_pages = 0; | ||||
|  | ||||
| #if defined(HCL_BUILD_DEBUG) | ||||
| 	const char* dbgopt = HCL_NULL; | ||||
| @ -1477,9 +1522,13 @@ int main (int argc, char* argv[]) | ||||
| 				break; | ||||
|  | ||||
| 			case '\0': | ||||
| 				 | ||||
| 				if (hcl_compbcstr(opt.lngopt, "large-pages") == 0) | ||||
| 				{ | ||||
| 					large_pages = 1; | ||||
| 					break; | ||||
| 				} | ||||
| 			#if defined(HCL_BUILD_DEBUG) | ||||
| 				if (hcl_compbcstr(opt.lngopt, "debug") == 0) | ||||
| 				else if (hcl_compbcstr(opt.lngopt, "debug") == 0) | ||||
| 				{ | ||||
| 					dbgopt = opt.arg; | ||||
| 					break; | ||||
| @ -1504,19 +1553,23 @@ int main (int argc, char* argv[]) | ||||
| 	if (opt.ind >= argc) goto print_usage; | ||||
| #endif | ||||
|  | ||||
|  | ||||
| 	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_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; | ||||
| 	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) | ||||
| 	{ | ||||
| 		printf ("cannot open hcl\n"); | ||||
|  | ||||
		Reference in New Issue
	
	Block a user