| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * $Id$ | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-02-07 14:13:13 +00:00
										 |  |  |     Copyright (c) 2016-2018 Chung, Hyung-Hwan. All rights reserved. | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Redistribution and use in source and binary forms, with or without | 
					
						
							|  |  |  |     modification, are permitted provided that the following conditions | 
					
						
							|  |  |  |     are met: | 
					
						
							|  |  |  |     1. Redistributions of source code must retain the above copyright | 
					
						
							|  |  |  |        notice, this list of conditions and the following disclaimer. | 
					
						
							|  |  |  |     2. Redistributions in binary form must reproduce the above copyright | 
					
						
							|  |  |  |        notice, this list of conditions and the following disclaimer in the | 
					
						
							|  |  |  |        documentation and/or other materials provided with the distribution. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR | 
					
						
							|  |  |  |     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 
					
						
							|  |  |  |     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 
					
						
							|  |  |  |     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 
					
						
							|  |  |  |     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 
					
						
							|  |  |  |     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
					
						
							|  |  |  |     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
					
						
							|  |  |  |     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
					
						
							|  |  |  |     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 
					
						
							|  |  |  |     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "hcl-prv.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-09 17:47:22 +00:00
										 |  |  | hcl_t* hcl_open (hcl_mmgr_t* mmgr, hcl_oow_t xtnsize, const hcl_vmprim_t* vmprim, hcl_errnum_t* errnum) | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	hcl_t* hcl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* if this assertion fails, correct the type definition in hcl.h */ | 
					
						
							| 
									
										
										
										
											2018-02-05 10:43:25 +00:00
										 |  |  | 	HCL_ASSERT (hcl, HCL_SIZEOF(hcl_oow_t) == HCL_SIZEOF(hcl_oop_t)); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-26 15:24:45 +00:00
										 |  |  | 	hcl = (hcl_t*)HCL_MMGR_ALLOC(mmgr, HCL_SIZEOF(*hcl) + xtnsize); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	if (hcl) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-02-09 17:47:22 +00:00
										 |  |  | 		if (hcl_init(hcl, mmgr, vmprim) <= -1) | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			if (errnum) *errnum = hcl->errnum; | 
					
						
							|  |  |  | 			HCL_MMGR_FREE (mmgr, hcl); | 
					
						
							|  |  |  | 			hcl = HCL_NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else HCL_MEMSET (hcl + 1, 0, xtnsize); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (errnum) *errnum = HCL_ESYSMEM; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return hcl; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hcl_close (hcl_t* hcl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_fini (hcl); | 
					
						
							| 
									
										
										
										
											2019-06-21 12:36:25 +00:00
										 |  |  | 	HCL_MMGR_FREE (hcl_getmmgr(hcl), hcl); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void fill_bigint_tables (hcl_t* hcl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int radix, safe_ndigits; | 
					
						
							|  |  |  | 	hcl_oow_t ub, w; | 
					
						
							|  |  |  | 	hcl_oow_t multiplier; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (radix = 2; radix <= 36; radix++) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		w = 0; | 
					
						
							|  |  |  | 		ub = (hcl_oow_t)HCL_TYPE_MAX(hcl_liw_t) / radix - (radix - 1); | 
					
						
							|  |  |  | 		multiplier = 1; | 
					
						
							|  |  |  | 		safe_ndigits = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		while (w <= ub) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			w = w * radix + (radix - 1); | 
					
						
							|  |  |  | 			multiplier *= radix; | 
					
						
							|  |  |  | 			safe_ndigits++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* safe_ndigits contains the number of digits that never
 | 
					
						
							|  |  |  | 		 * cause overflow when computed normally with a native type. */ | 
					
						
							|  |  |  | 		hcl->bigint[radix].safe_ndigits = safe_ndigits; | 
					
						
							|  |  |  | 		hcl->bigint[radix].multiplier = multiplier; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-24 13:50:51 +00:00
										 |  |  | static void* alloc_heap (hcl_t* hcl, hcl_oow_t* size) | 
					
						
							| 
									
										
										
										
											2018-03-01 14:47:12 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-04-24 13:50:51 +00:00
										 |  |  | 	return hcl_allocmem(hcl, *size); | 
					
						
							| 
									
										
										
										
											2018-03-01 14:47:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void free_heap (hcl_t* hcl, void* ptr) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-06-21 12:36:25 +00:00
										 |  |  | 	hcl_freemem (hcl, ptr); | 
					
						
							| 
									
										
										
										
											2018-03-01 14:47:12 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-09 17:47:22 +00:00
										 |  |  | int hcl_init (hcl_t* hcl, hcl_mmgr_t* mmgr, const hcl_vmprim_t* vmprim) | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-02-20 14:53:12 +00:00
										 |  |  | 	int modtab_inited = 0; | 
					
						
							| 
									
										
										
										
											2020-09-22 09:19:53 +00:00
										 |  |  | 	int n; | 
					
						
							| 
									
										
										
										
											2018-02-20 14:53:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!vmprim->syserrstrb && !vmprim->syserrstru) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_seterrnum (hcl, HCL_EINVAL); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-03 15:57:14 +00:00
										 |  |  | #if !defined(HCL_BUILD_RELEASE)
 | 
					
						
							|  |  |  | 	if (!vmprim->assertfail) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_seterrnum (hcl, HCL_EINVAL); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	HCL_MEMSET (hcl, 0, HCL_SIZEOF(*hcl)); | 
					
						
							| 
									
										
										
										
											2019-06-21 12:36:25 +00:00
										 |  |  | 	hcl->_instsize = HCL_SIZEOF(*hcl); | 
					
						
							|  |  |  | 	hcl->_mmgr = mmgr; | 
					
						
							|  |  |  | 	hcl->_cmgr = hcl_get_utf8_cmgr(); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	hcl->vmprim = *vmprim; | 
					
						
							| 
									
										
										
										
											2018-03-01 14:47:12 +00:00
										 |  |  | 	if (!hcl->vmprim.alloc_heap) hcl->vmprim.alloc_heap = alloc_heap; | 
					
						
							|  |  |  | 	if (!hcl->vmprim.free_heap) hcl->vmprim.free_heap = free_heap; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-11 14:14:49 +00:00
										 |  |  | 	/*hcl->option.log_mask = HCL_LOG_ALL_LEVELS | HCL_LOG_ALL_TYPES;*/ | 
					
						
							|  |  |  | 	hcl->option.log_mask = (hcl_bitmask_t)0; /* log nothing by default */ | 
					
						
							| 
									
										
										
										
											2018-02-05 10:43:25 +00:00
										 |  |  | 	hcl->option.log_maxcapa = HCL_DFL_LOG_MAXCAPA; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	hcl->option.dfl_symtab_size = HCL_DFL_SYMTAB_SIZE; | 
					
						
							|  |  |  | 	hcl->option.dfl_sysdic_size = HCL_DFL_SYSDIC_SIZE; | 
					
						
							|  |  |  | 	hcl->option.dfl_procstk_size = HCL_DFL_PROCSTK_SIZE; | 
					
						
							| 
									
										
										
										
											2018-02-21 09:30:18 +00:00
										 |  |  | #if defined(HCL_BUILD_DEBUG)
 | 
					
						
							| 
									
										
										
										
											2018-02-20 14:53:12 +00:00
										 |  |  | 	hcl->option.karatsuba_cutoff = HCL_KARATSUBA_CUTOFF; /* this won't be used when NDEBUG is set */ | 
					
						
							| 
									
										
										
										
											2018-02-21 09:30:18 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-05 10:43:25 +00:00
										 |  |  | 	hcl->log.capa = HCL_ALIGN_POW2(1, HCL_LOG_CAPA_ALIGN); /* TODO: is this a good initial size? */ | 
					
						
							|  |  |  | 	/* alloate the log buffer in advance though it may get reallocated
 | 
					
						
							|  |  |  | 	 * in put_oocs and put_ooch in logfmt.c. this is to let the logging | 
					
						
							|  |  |  | 	 * routine still function despite some side-effects when | 
					
						
							|  |  |  | 	 * reallocation fails */ | 
					
						
							|  |  |  | 	/* +1 required for consistency with put_oocs and put_ooch in logfmt.c */ | 
					
						
							| 
									
										
										
										
											2018-03-01 14:47:12 +00:00
										 |  |  | 	hcl->log.ptr = (hcl_ooch_t*)hcl_allocmem(hcl, (hcl->log.capa + 1) * HCL_SIZEOF(*hcl->log.ptr));  | 
					
						
							| 
									
										
										
										
											2020-09-22 09:19:53 +00:00
										 |  |  | 	if (HCL_UNLIKELY(!hcl->log.ptr)) goto oops; | 
					
						
							| 
									
										
										
										
											2018-02-05 10:43:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-31 17:48:47 +00:00
										 |  |  | 	hcl->gci.stack.capa = HCL_ALIGN_POW2(1, 1024); /* TODO: is this a good initial size? */ | 
					
						
							|  |  |  | 	hcl->gci.stack.ptr = hcl_allocmem(hcl, (hcl->gci.stack.capa + 1) * HCL_SIZEOF(*hcl->gci.stack.ptr)); | 
					
						
							|  |  |  | 	if (HCL_UNLIKELY(!hcl->gci.stack.ptr)) goto oops; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-22 09:19:53 +00:00
										 |  |  | 	n = hcl_rbt_init(&hcl->modtab, hcl, HCL_SIZEOF(hcl_ooch_t), 1); | 
					
						
							|  |  |  | 	if (HCL_UNLIKELY(n <= -1)) goto oops; | 
					
						
							| 
									
										
										
										
											2018-02-20 14:53:12 +00:00
										 |  |  | 	modtab_inited = 1; | 
					
						
							| 
									
										
										
										
											2019-11-18 14:09:57 +00:00
										 |  |  | 	hcl_rbt_setstyle(&hcl->modtab, hcl_get_rbt_style(HCL_RBT_STYLE_INLINE_COPIERS)); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	fill_bigint_tables (hcl); | 
					
						
							| 
									
										
										
										
											2018-02-08 09:21:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-23 07:17:23 +00:00
										 |  |  | 	hcl->tagged_brands[HCL_OOP_TAG_SMOOI] = HCL_BRAND_SMOOI; | 
					
						
							|  |  |  | 	hcl->tagged_brands[HCL_OOP_TAG_SMPTR] = HCL_BRAND_SMPTR; | 
					
						
							|  |  |  | 	hcl->tagged_brands[HCL_OOP_TAG_CHAR] = HCL_BRAND_CHARACTER; | 
					
						
							|  |  |  | 	hcl->tagged_brands[HCL_OOP_TAG_ERROR] = HCL_BRAND_ERROR; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-08 09:21:18 +00:00
										 |  |  | 	hcl->proc_map_free_first = -1; | 
					
						
							|  |  |  | 	hcl->proc_map_free_last = -1; | 
					
						
							| 
									
										
										
										
											2018-02-20 14:53:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-03 15:57:14 +00:00
										 |  |  | 	if (hcl->vmprim.dl_startup) hcl->vmprim.dl_startup (hcl); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | oops: | 
					
						
							| 
									
										
										
										
											2018-03-05 04:08:11 +00:00
										 |  |  | 	if (modtab_inited) hcl_rbt_fini (&hcl->modtab); | 
					
						
							| 
									
										
										
										
											2020-12-31 17:48:47 +00:00
										 |  |  | 	if (hcl->gci.stack.ptr) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_freemem (hcl, hcl->gci.stack.ptr); | 
					
						
							|  |  |  | 		hcl->gci.stack.capa = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-02-05 10:43:25 +00:00
										 |  |  | 	if (hcl->log.ptr) hcl_freemem (hcl, hcl->log.ptr); | 
					
						
							|  |  |  | 	hcl->log.capa = 0; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | static hcl_rbt_walk_t unload_module (hcl_rbt_t* rbt, hcl_rbt_pair_t* pair, void* ctx) | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	hcl_t* hcl = (hcl_t*)ctx; | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 	hcl_mod_data_t* mdp; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-26 15:24:45 +00:00
										 |  |  | 	mdp = (hcl_mod_data_t*)HCL_RBT_VPTR(pair); | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 	HCL_ASSERT (hcl, mdp != HCL_NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mdp->pair = HCL_NULL; /* to prevent hcl_closemod() from calling  hcl_rbt_delete() */ | 
					
						
							|  |  |  | 	hcl_closemod (hcl, mdp); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return HCL_RBT_WALK_FORWARD; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hcl_fini (hcl_t* hcl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_cb_t* cb; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 	hcl_rbt_walk (&hcl->modtab, unload_module, hcl); | 
					
						
							|  |  |  | 	hcl_rbt_fini (&hcl->modtab); | 
					
						
							| 
									
										
										
										
											2018-02-05 10:43:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (hcl->log.len > 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* flush pending log messages just in case. */ | 
					
						
							|  |  |  | 		HCL_ASSERT (hcl, hcl->log.ptr != HCL_NULL); | 
					
						
							| 
									
										
										
										
											2018-02-22 04:35:55 +00:00
										 |  |  | 		vmprim_log_write (hcl, hcl->log.last_mask, hcl->log.ptr, hcl->log.len); | 
					
						
							| 
									
										
										
										
											2018-02-05 10:43:25 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (cb = hcl->cblist; cb; cb = cb->next) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (cb->fini) cb->fini (hcl); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (hcl->log.len > 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* flush pending log message that could be generated by the fini 
 | 
					
						
							|  |  |  | 		 * callbacks. however, the actual logging might not be produced at | 
					
						
							|  |  |  | 		 * this point because one of the callbacks could arrange to stop | 
					
						
							|  |  |  | 		 * logging */ | 
					
						
							|  |  |  | 		HCL_ASSERT (hcl, hcl->log.ptr != HCL_NULL); | 
					
						
							| 
									
										
										
										
											2018-02-22 04:35:55 +00:00
										 |  |  | 		vmprim_log_write (hcl, hcl->log.last_mask, hcl->log.ptr, hcl->log.len); | 
					
						
							| 
									
										
										
										
											2018-02-05 10:43:25 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* deregister all callbacks */ | 
					
						
							|  |  |  | 	while (hcl->cblist) hcl_deregcb (hcl, hcl->cblist); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	if (hcl->sem_list) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_freemem (hcl, hcl->sem_list); | 
					
						
							|  |  |  | 		hcl->sem_list_capa = 0; | 
					
						
							|  |  |  | 		hcl->sem_list_count = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (hcl->sem_heap) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_freemem (hcl, hcl->sem_heap); | 
					
						
							|  |  |  | 		hcl->sem_heap_capa = 0; | 
					
						
							|  |  |  | 		hcl->sem_heap_count = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-15 12:57:05 +00:00
										 |  |  | 	if (hcl->sem_io_tuple) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_freemem (hcl, hcl->sem_io_tuple); | 
					
						
							|  |  |  | 		hcl->sem_io_tuple_capa = 0; | 
					
						
							|  |  |  | 		hcl->sem_io_tuple_count = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (hcl->sem_io_map) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_freemem (hcl, hcl->sem_io_map); | 
					
						
							|  |  |  | 		hcl->sem_io_map_capa = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-08 09:21:18 +00:00
										 |  |  | 	if (hcl->proc_map) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_freemem (hcl, hcl->proc_map); | 
					
						
							|  |  |  | 		hcl->proc_map_capa = 0; | 
					
						
							| 
									
										
										
										
											2020-10-15 12:57:05 +00:00
										 |  |  | 		hcl->proc_map_used = 0; | 
					
						
							| 
									
										
										
										
											2018-02-08 09:21:18 +00:00
										 |  |  | 		hcl->proc_map_free_first = -1; | 
					
						
							|  |  |  | 		hcl->proc_map_free_last = -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-01 03:32:09 +00:00
										 |  |  | 	if (hcl->code.dbgi) | 
					
						
							| 
									
										
										
										
											2021-01-03 13:51:23 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-02-01 03:32:09 +00:00
										 |  |  | 		hcl_freemem (hcl, hcl->code.dbgi); | 
					
						
							|  |  |  | 		hcl->code.dbgi = HCL_NULL; | 
					
						
							| 
									
										
										
										
											2021-01-03 13:51:23 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-08 09:25:54 +00:00
										 |  |  | 	if (hcl->code.bc.ptr) | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-10-08 09:25:54 +00:00
										 |  |  | 		hcl_freemem (hcl, hcl->code.bc.ptr); | 
					
						
							|  |  |  | 		hcl->code.bc.ptr = HCL_NULL; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 		hcl->code.bc.len = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (hcl->code.lit.arr) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-02-12 16:51:38 +00:00
										 |  |  | 		hcl_freengcobj (hcl, (hcl_oop_t)hcl->code.lit.arr); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 		hcl->code.lit.arr = HCL_NULL; | 
					
						
							|  |  |  | 		hcl->code.lit.len = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (hcl->p.s.ptr) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_freemem (hcl, hcl->p.s.ptr); | 
					
						
							|  |  |  | 		hcl->p.s.ptr= HCL_NULL; | 
					
						
							|  |  |  | 		hcl->p.s.capa = 0; | 
					
						
							|  |  |  | 		hcl->p.s.size = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-31 17:48:47 +00:00
										 |  |  | 	if (hcl->gci.b) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_gchdr_t* next; | 
					
						
							|  |  |  | 		do | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			next = hcl->gci.b->next; | 
					
						
							|  |  |  | 			hcl->gci.bsz -= HCL_SIZEOF(hcl_obj_t) + hcl_getobjpayloadbytes(hcl, (hcl_oop_t)(hcl->gci.b + 1)); | 
					
						
							|  |  |  | 			hcl_freeheapmem (hcl, hcl->heap, hcl->gci.b); | 
					
						
							|  |  |  | 			hcl->gci.b = next; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		while (hcl->gci.b); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		HCL_ASSERT (hcl, hcl->gci.bsz == 0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (hcl->gci.stack.ptr) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_freemem (hcl, hcl->gci.stack.ptr); | 
					
						
							|  |  |  | 		hcl->gci.stack.ptr = 0; | 
					
						
							|  |  |  | 		hcl->gci.stack.capa = 0; | 
					
						
							|  |  |  | 		hcl->gci.stack.len = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-09 14:54:54 +00:00
										 |  |  | 	if (hcl->heap) hcl_killheap (hcl, hcl->heap); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (hcl->log.ptr)  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_freemem (hcl, hcl->log.ptr); | 
					
						
							|  |  |  | 		hcl->log.capa = 0; | 
					
						
							|  |  |  | 		hcl->log.len = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-02-15 06:58:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-19 07:11:41 +00:00
										 |  |  | 	if (hcl->option.log_target_u) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:57:35 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-07-19 07:11:41 +00:00
										 |  |  | 		hcl_freemem (hcl, hcl->option.log_target_u); | 
					
						
							|  |  |  | 		hcl->option.log_target_u = HCL_NULL; | 
					
						
							| 
									
										
										
										
											2021-02-07 17:57:35 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-19 07:11:41 +00:00
										 |  |  | 	if (hcl->option.log_target_b) | 
					
						
							| 
									
										
										
										
											2021-02-07 17:57:35 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2021-07-19 07:11:41 +00:00
										 |  |  | 		hcl_freemem (hcl, hcl->option.log_target_b); | 
					
						
							|  |  |  | 		hcl->option.log_target_b = HCL_NULL; | 
					
						
							| 
									
										
										
										
											2021-02-07 17:57:35 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-15 06:58:36 +00:00
										 |  |  | 	if (hcl->inttostr.xbuf.ptr) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_freemem (hcl, hcl->inttostr.xbuf.ptr); | 
					
						
							|  |  |  | 		hcl->inttostr.xbuf.ptr = HCL_NULL; | 
					
						
							|  |  |  | 		hcl->inttostr.xbuf.capa = 0; | 
					
						
							| 
									
										
										
										
											2018-02-15 08:05:48 +00:00
										 |  |  | 		hcl->inttostr.xbuf.len = 0; | 
					
						
							| 
									
										
										
										
											2018-02-15 06:58:36 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (hcl->inttostr.t.ptr) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_freemem (hcl, hcl->inttostr.t.ptr); | 
					
						
							|  |  |  | 		hcl->inttostr.t.ptr = HCL_NULL; | 
					
						
							|  |  |  | 		hcl->inttostr.t.capa = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-03-05 03:35:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (hcl->sprintf.xbuf.ptr) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl_freemem (hcl, hcl->sprintf.xbuf.ptr); | 
					
						
							|  |  |  | 		hcl->sprintf.xbuf.ptr = HCL_NULL; | 
					
						
							|  |  |  | 		hcl->sprintf.xbuf.capa = 0; | 
					
						
							|  |  |  | 		hcl->sprintf.xbuf.len = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-11-03 15:57:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (hcl->vmprim.dl_cleanup) hcl->vmprim.dl_cleanup (hcl); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-12 02:50:37 +00:00
										 |  |  | void hcl_reset (hcl_t* hcl) | 
					
						
							| 
									
										
										
										
											2018-02-24 04:01:19 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-03-08 10:00:57 +00:00
										 |  |  | 	hcl_oop_t v; | 
					
						
							|  |  |  | 	hcl_oow_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-08 14:18:30 +00:00
										 |  |  | 	/* delete all literals shown in the literal frame from the system dictionary 
 | 
					
						
							|  |  |  | 	 * excluding special kernel symbols. */ | 
					
						
							| 
									
										
										
										
											2018-03-08 10:00:57 +00:00
										 |  |  | 	for (i = 0; i < hcl->code.lit.len; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-03-08 14:18:30 +00:00
										 |  |  | 		v = ((hcl_oop_oop_t)hcl->code.lit.arr)->slot[i]; | 
					
						
							|  |  |  | 		if (HCL_IS_CONS(hcl, v)) | 
					
						
							| 
									
										
										
										
											2018-03-08 10:00:57 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2018-03-08 14:18:30 +00:00
										 |  |  | 			hcl_oop_t key = HCL_CONS_CAR(v); | 
					
						
							|  |  |  | 			if (!HCL_IS_SYMBOL(hcl,key) || !HCL_OBJ_GET_FLAGS_KERNEL(key)) | 
					
						
							|  |  |  | 				hcl_zapatsysdic (hcl, HCL_CONS_CAR(v)); | 
					
						
							| 
									
										
										
										
											2018-03-08 10:00:57 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-03-08 14:18:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* zap the byte code buffer and the literal frame */ | 
					
						
							| 
									
										
										
										
											2018-03-08 10:00:57 +00:00
										 |  |  | 	hcl->code.bc.len = 0; | 
					
						
							|  |  |  | 	hcl->code.lit.len = 0; | 
					
						
							| 
									
										
										
										
											2018-03-08 14:18:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* clean up object memory */ | 
					
						
							| 
									
										
										
										
											2020-12-31 17:48:47 +00:00
										 |  |  | 	hcl_gc (hcl, 1); | 
					
						
							| 
									
										
										
										
											2018-02-24 04:01:19 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-12 02:50:37 +00:00
										 |  |  | void hcl_setinloc (hcl_t* hcl, hcl_oow_t line, hcl_oow_t colm) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl->c->inarg.line = line; | 
					
						
							|  |  |  | 	hcl->c->inarg.colm = colm; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | int hcl_setoption (hcl_t* hcl, hcl_option_t id, const void* value) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-02-07 17:57:35 +00:00
										 |  |  | 	hcl_cb_t* cb; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	switch (id) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		case HCL_TRAIT: | 
					
						
							| 
									
										
										
										
											2018-04-26 04:39:20 +00:00
										 |  |  | 			hcl->option.trait = *(const hcl_bitmask_t*)value; | 
					
						
							| 
									
										
										
										
											2018-02-21 09:30:18 +00:00
										 |  |  | 		#if defined(HCL_BUILD_DEBUG)
 | 
					
						
							| 
									
										
										
										
											2021-02-01 03:32:09 +00:00
										 |  |  | 			hcl->option.karatsuba_cutoff = ((hcl->option.trait & HCL_TRAIT_DEBUG_BIGINT)? HCL_KARATSUBA_CUTOFF_DEBUG: HCL_KARATSUBA_CUTOFF); | 
					
						
							| 
									
										
										
										
											2018-02-05 10:43:25 +00:00
										 |  |  | 		#endif
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:57:35 +00:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case HCL_LOG_MASK: | 
					
						
							| 
									
										
										
										
											2018-04-26 04:39:20 +00:00
										 |  |  | 			hcl->option.log_mask = *(const hcl_bitmask_t*)value; | 
					
						
							| 
									
										
										
										
											2021-02-07 17:57:35 +00:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-05 10:43:25 +00:00
										 |  |  | 		case HCL_LOG_MAXCAPA: | 
					
						
							|  |  |  | 			hcl->option.log_maxcapa = *(hcl_oow_t*)value; | 
					
						
							| 
									
										
										
										
											2021-02-07 17:57:35 +00:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-19 07:11:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-19 18:59:17 +00:00
										 |  |  | 		case HCL_LOG_TARGET_BCSTR: | 
					
						
							| 
									
										
										
										
											2021-02-07 17:57:35 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2021-07-19 07:11:41 +00:00
										 |  |  | 			hcl_bch_t* v1; | 
					
						
							| 
									
										
										
										
											2021-02-07 17:57:35 +00:00
										 |  |  | 			hcl_uch_t* v2; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-19 07:11:41 +00:00
										 |  |  | 			v1 = hcl_dupbcstr(hcl, value, HCL_NULL); | 
					
						
							| 
									
										
										
										
											2021-02-07 17:57:35 +00:00
										 |  |  | 			if (HCL_UNLIKELY(!v1)) return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-19 07:11:41 +00:00
										 |  |  | 			v2 = hcl_dupbtoucstr(hcl, value, HCL_NULL); | 
					
						
							| 
									
										
										
										
											2021-02-07 17:57:35 +00:00
										 |  |  | 			if (HCL_UNLIKELY(!v2)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				hcl_freemem (hcl, v1); | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-07-19 07:11:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			hcl->option.log_target_u = v2; | 
					
						
							|  |  |  | 			hcl->option.log_target_b = v1; | 
					
						
							| 
									
										
										
										
											2021-02-07 17:57:35 +00:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-19 18:59:17 +00:00
										 |  |  | 		case HCL_LOG_TARGET_UCSTR: | 
					
						
							| 
									
										
										
										
											2021-07-19 07:11:41 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			hcl_uch_t* v1; | 
					
						
							|  |  |  | 			hcl_bch_t* v2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			v1 = hcl_dupucstr(hcl, value, HCL_NULL); | 
					
						
							|  |  |  | 			if (HCL_UNLIKELY(!v1)) return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			v2 = hcl_duputobcstr(hcl, value, HCL_NULL); | 
					
						
							|  |  |  | 			if (HCL_UNLIKELY(!v2)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				hcl_freemem (hcl, v1); | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			hcl->option.log_target_u = v1; | 
					
						
							|  |  |  | 			hcl->option.log_target_b = v2; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-02-05 10:43:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-19 18:59:17 +00:00
										 |  |  | 		case HCL_LOG_TARGET_BCS: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hcl_bch_t* v1; | 
					
						
							|  |  |  | 			hcl_uch_t* v2; | 
					
						
							|  |  |  | 			hcl_bcs_t* v = (hcl_bcs_t*)value; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			v1 = hcl_dupbchars(hcl, v->ptr, v->len); | 
					
						
							|  |  |  | 			if (HCL_UNLIKELY(!v1)) return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			v2 = hcl_dupbtouchars(hcl, v->ptr, v->len, HCL_NULL); | 
					
						
							|  |  |  | 			if (HCL_UNLIKELY(!v2)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				hcl_freemem (hcl, v1); | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			hcl->option.log_target_u = v2; | 
					
						
							|  |  |  | 			hcl->option.log_target_b = v1; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case HCL_LOG_TARGET_UCS: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hcl_uch_t* v1; | 
					
						
							|  |  |  | 			hcl_bch_t* v2; | 
					
						
							| 
									
										
										
										
											2021-07-24 15:28:59 +00:00
										 |  |  | 			hcl_ucs_t* v = (hcl_ucs_t*)value; | 
					
						
							| 
									
										
										
										
											2021-07-19 18:59:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			v1 = hcl_dupuchars(hcl, v->ptr, v->len); | 
					
						
							|  |  |  | 			if (HCL_UNLIKELY(!v1)) return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			v2 = hcl_duputobchars(hcl, v->ptr, v->len, HCL_NULL); | 
					
						
							|  |  |  | 			if (HCL_UNLIKELY(!v2)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				hcl_freemem (hcl, v1); | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			hcl->option.log_target_u = v1; | 
					
						
							|  |  |  | 			hcl->option.log_target_b = v2; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 		case HCL_SYMTAB_SIZE: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hcl_oow_t w; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			w = *(hcl_oow_t*)value; | 
					
						
							|  |  |  | 			if (w <= 0 || w > HCL_SMOOI_MAX) goto einval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			hcl->option.dfl_symtab_size = *(hcl_oow_t*)value; | 
					
						
							| 
									
										
										
										
											2021-02-07 17:57:35 +00:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case HCL_SYSDIC_SIZE: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hcl_oow_t w; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			w = *(hcl_oow_t*)value; | 
					
						
							|  |  |  | 			if (w <= 0 || w > HCL_SMOOI_MAX) goto einval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			hcl->option.dfl_sysdic_size = *(hcl_oow_t*)value; | 
					
						
							| 
									
										
										
										
											2021-02-07 17:57:35 +00:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case HCL_PROCSTK_SIZE: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hcl_oow_t w; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			w = *(hcl_oow_t*)value; | 
					
						
							|  |  |  | 			if (w <= 0 || w > HCL_SMOOI_MAX) goto einval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			hcl->option.dfl_procstk_size = *(hcl_oow_t*)value; | 
					
						
							| 
									
										
										
										
											2021-02-07 17:57:35 +00:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-04-09 15:54:54 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 		case HCL_MOD_INCTX: | 
					
						
							|  |  |  | 			hcl->option.mod_inctx = *(void**)value; | 
					
						
							| 
									
										
										
										
											2021-02-07 17:57:35 +00:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			goto einval; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (cb = hcl->cblist; cb; cb = cb->next)  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (cb->opt_set) cb->opt_set (hcl, id, value); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 17:57:35 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | einval: | 
					
						
							| 
									
										
										
										
											2018-02-05 10:43:25 +00:00
										 |  |  | 	hcl_seterrnum (hcl, HCL_EINVAL); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int hcl_getoption (hcl_t* hcl, hcl_option_t id, void* value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	switch  (id) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		case HCL_TRAIT: | 
					
						
							| 
									
										
										
										
											2018-04-26 04:39:20 +00:00
										 |  |  | 			*(hcl_bitmask_t*)value = hcl->option.trait; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 			return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case HCL_LOG_MASK: | 
					
						
							| 
									
										
										
										
											2018-04-26 04:39:20 +00:00
										 |  |  | 			*(hcl_bitmask_t*)value = hcl->option.log_mask; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 			return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-05 10:43:25 +00:00
										 |  |  | 		case HCL_LOG_MAXCAPA: | 
					
						
							|  |  |  | 			*(hcl_oow_t*)value = hcl->option.log_maxcapa; | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-19 18:59:17 +00:00
										 |  |  | 		case HCL_LOG_TARGET_BCSTR: | 
					
						
							| 
									
										
										
										
											2021-07-19 07:11:41 +00:00
										 |  |  | 			*(hcl_bch_t**)value = hcl->option.log_target_b; | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-19 18:59:17 +00:00
										 |  |  | 		case HCL_LOG_TARGET_UCSTR: | 
					
						
							| 
									
										
										
										
											2021-07-19 07:11:41 +00:00
										 |  |  | 			*(hcl_uch_t**)value = hcl->option.log_target_u; | 
					
						
							| 
									
										
										
										
											2021-02-07 17:57:35 +00:00
										 |  |  | 			return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-19 18:59:17 +00:00
										 |  |  | 		case HCL_LOG_TARGET_BCS: | 
					
						
							|  |  |  | 			((hcl_bcs_t*)value)->ptr = hcl->option.log_target_b; | 
					
						
							|  |  |  | 			((hcl_bcs_t*)value)->len = hcl_count_bcstr(hcl->option.log_target_b); | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case HCL_LOG_TARGET_UCS: | 
					
						
							|  |  |  | 			((hcl_ucs_t*)value)->ptr = hcl->option.log_target_u; | 
					
						
							|  |  |  | 			((hcl_ucs_t*)value)->len = hcl_count_ucstr(hcl->option.log_target_u); | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 		case HCL_SYMTAB_SIZE: | 
					
						
							|  |  |  | 			*(hcl_oow_t*)value = hcl->option.dfl_symtab_size; | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case HCL_SYSDIC_SIZE: | 
					
						
							|  |  |  | 			*(hcl_oow_t*)value = hcl->option.dfl_sysdic_size; | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case HCL_PROCSTK_SIZE: | 
					
						
							|  |  |  | 			*(hcl_oow_t*)value = hcl->option.dfl_procstk_size; | 
					
						
							|  |  |  | 			return 0; | 
					
						
							| 
									
										
										
										
											2018-04-09 15:54:54 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case HCL_MOD_INCTX: | 
					
						
							|  |  |  | 			*(void**)value = hcl->option.mod_inctx; | 
					
						
							|  |  |  | 			return 0; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-05 10:43:25 +00:00
										 |  |  | 	hcl_seterrnum (hcl, HCL_EINVAL); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | hcl_cb_t* hcl_regcb (hcl_t* hcl, hcl_cb_t* tmpl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	hcl_cb_t* actual; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-26 15:24:45 +00:00
										 |  |  | 	actual = (hcl_cb_t*)hcl_allocmem(hcl, HCL_SIZEOF(*actual)); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	if (!actual) return HCL_NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*actual = *tmpl; | 
					
						
							|  |  |  | 	actual->next = hcl->cblist; | 
					
						
							|  |  |  | 	actual->prev = HCL_NULL; | 
					
						
							|  |  |  | 	hcl->cblist = actual; | 
					
						
							| 
									
										
										
										
											2018-03-10 17:53:44 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2018-03-11 11:16:28 +00:00
										 |  |  | 	/* vm_checkbc is invoked very frequently.
 | 
					
						
							|  |  |  | 	 * and there might be multiple vm_checkbc callbacks registered. | 
					
						
							|  |  |  | 	 * keeping the count of vm_checkbc callbacks registered | 
					
						
							| 
									
										
										
										
											2018-03-11 03:05:42 +00:00
										 |  |  | 	 * speeds up the check */ | 
					
						
							| 
									
										
										
										
											2018-03-11 11:16:28 +00:00
										 |  |  | 	if (actual->vm_checkbc) hcl->vm_checkbc_cb_count++; | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return actual; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hcl_deregcb (hcl_t* hcl, hcl_cb_t* cb) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (cb == hcl->cblist) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl->cblist = hcl->cblist->next; | 
					
						
							|  |  |  | 		if (hcl->cblist) hcl->cblist->prev = HCL_NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (cb->next) cb->next->prev = cb->prev; | 
					
						
							|  |  |  | 		if (cb->prev) cb->prev->next = cb->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-11 11:16:28 +00:00
										 |  |  | 	if (cb->vm_checkbc)  | 
					
						
							| 
									
										
										
										
											2018-03-10 17:53:44 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-03-11 11:16:28 +00:00
										 |  |  | 		HCL_ASSERT (hcl, hcl->vm_checkbc_cb_count > 0); | 
					
						
							|  |  |  | 		hcl->vm_checkbc_cb_count--; | 
					
						
							| 
									
										
										
										
											2018-03-10 17:53:44 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	hcl_freemem (hcl, cb); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void* hcl_allocmem (hcl_t* hcl, hcl_oow_t size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	void* ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-21 12:36:25 +00:00
										 |  |  | 	ptr = HCL_MMGR_ALLOC (hcl_getmmgr(hcl), size); | 
					
						
							| 
									
										
										
										
											2018-02-05 10:43:25 +00:00
										 |  |  | 	if (!ptr) hcl_seterrnum (hcl, HCL_ESYSMEM); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	return ptr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void* hcl_callocmem (hcl_t* hcl, hcl_oow_t size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	void* ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-21 12:36:25 +00:00
										 |  |  | 	ptr = HCL_MMGR_ALLOC (hcl_getmmgr(hcl), size); | 
					
						
							| 
									
										
										
										
											2018-02-05 10:43:25 +00:00
										 |  |  | 	if (!ptr) hcl_seterrnum (hcl, HCL_ESYSMEM); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	else HCL_MEMSET (ptr, 0, size); | 
					
						
							|  |  |  | 	return ptr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void* hcl_reallocmem (hcl_t* hcl, void* ptr, hcl_oow_t size) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-06-21 12:36:25 +00:00
										 |  |  | 	ptr = HCL_MMGR_REALLOC (hcl_getmmgr(hcl), ptr, size); | 
					
						
							| 
									
										
										
										
											2018-02-05 10:43:25 +00:00
										 |  |  | 	if (!ptr) hcl_seterrnum (hcl, HCL_ESYSMEM); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | 	return ptr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hcl_freemem (hcl_t* hcl, void* ptr) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-06-21 12:36:25 +00:00
										 |  |  | 	HCL_MMGR_FREE (hcl_getmmgr(hcl), ptr); | 
					
						
							| 
									
										
										
										
											2016-09-28 14:40:37 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define MOD_PREFIX "hcl_mod_"
 | 
					
						
							|  |  |  | #define MOD_PREFIX_LEN 8
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(HCL_ENABLE_STATIC_MODULE)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-15 15:36:15 +00:00
										 |  |  | #include "../mod/_arr.h"
 | 
					
						
							|  |  |  | #include "../mod/_dic.h"
 | 
					
						
							|  |  |  | #include "../mod/_str.h"
 | 
					
						
							| 
									
										
										
										
											2019-04-17 03:46:39 +00:00
										 |  |  | #include "../mod/_sys.h"
 | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static struct | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-05-04 17:56:45 +00:00
										 |  |  | 	const hcl_bch_t* modname; | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 	int (*modload) (hcl_t* hcl, hcl_mod_t* mod); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | static_modtab[] =  | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-02-15 15:36:15 +00:00
										 |  |  | 	{ "arr",      hcl_mod_arr }, | 
					
						
							|  |  |  | 	{ "dic",      hcl_mod_dic }, | 
					
						
							| 
									
										
										
										
											2019-04-17 03:46:39 +00:00
										 |  |  | 	{ "str",      hcl_mod_str }, | 
					
						
							|  |  |  | 	{ "sys",      hcl_mod_sys } | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-12 16:51:38 +00:00
										 |  |  | hcl_mod_data_t* hcl_openmod (hcl_t* hcl, const hcl_ooch_t* name, hcl_oow_t namelen) | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	hcl_rbt_pair_t* pair; | 
					
						
							|  |  |  | 	hcl_mod_data_t* mdp; | 
					
						
							|  |  |  | 	hcl_mod_data_t md; | 
					
						
							|  |  |  | 	hcl_mod_load_t load = HCL_NULL; | 
					
						
							|  |  |  | #if defined(HCL_ENABLE_STATIC_MODULE)
 | 
					
						
							|  |  |  | 	int n; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* maximum module name length is HCL_MOD_NAME_LEN_MAX. 
 | 
					
						
							|  |  |  | 	 *   MOD_PREFIX_LEN for MOD_PREFIX | 
					
						
							|  |  |  | 	 *   1 for _ at the end when hcl_mod_xxx_ is attempted. | 
					
						
							|  |  |  | 	 *   1 for the terminating '\0'. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	hcl_ooch_t buf[MOD_PREFIX_LEN + HCL_MOD_NAME_LEN_MAX + 1 + 1];  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* copy instead of encoding conversion. MOD_PREFIX must not
 | 
					
						
							|  |  |  | 	 * include a character that requires encoding conversion. | 
					
						
							|  |  |  | 	 * note the terminating null isn't needed in buf here. */ | 
					
						
							| 
									
										
										
										
											2018-04-07 15:54:16 +00:00
										 |  |  | 	hcl_copy_bchars_to_oochars (buf, MOD_PREFIX, MOD_PREFIX_LEN);  | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (namelen > HCL_COUNTOF(buf) - (MOD_PREFIX_LEN + 1 + 1)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* module name too long  */ | 
					
						
							|  |  |  | 		hcl_seterrnum (hcl, HCL_EINVAL); /* TODO: change the  error number to something more specific */ | 
					
						
							|  |  |  | 		return HCL_NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-07 15:54:16 +00:00
										 |  |  | 	hcl_copy_oochars (&buf[MOD_PREFIX_LEN], name, namelen); | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 	buf[MOD_PREFIX_LEN + namelen] = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(HCL_ENABLE_STATIC_MODULE)
 | 
					
						
							|  |  |  | 	/* attempt to find a statically linked module */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* TODO: binary search ... */ | 
					
						
							|  |  |  | 	for (n = 0; n < HCL_COUNTOF(static_modtab); n++) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-04-07 15:54:16 +00:00
										 |  |  | 		if (hcl_comp_oochars_bcstr(name, namelen, static_modtab[n].modname) == 0)  | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			load = static_modtab[n].modload; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (load) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* found the module in the staic module table */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		HCL_MEMSET (&md, 0, HCL_SIZEOF(md)); | 
					
						
							| 
									
										
										
										
											2018-04-09 15:54:54 +00:00
										 |  |  | 		md.mod.inctx = hcl->option.mod_inctx; | 
					
						
							| 
									
										
										
										
											2018-04-07 15:54:16 +00:00
										 |  |  | 		hcl_copy_oochars ((hcl_ooch_t*)md.mod.name, name, namelen); | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 		/* Note md.handle is HCL_NULL for a static module */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* i copy-insert 'md' into the table before calling 'load'.
 | 
					
						
							|  |  |  | 		 * to pass the same address to load(), query(), etc */ | 
					
						
							| 
									
										
										
										
											2018-02-12 16:51:38 +00:00
										 |  |  | 		pair = hcl_rbt_insert(&hcl->modtab, (hcl_ooch_t*)name, namelen, &md, HCL_SIZEOF(md)); | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 		if (pair == HCL_NULL) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			hcl_seterrnum (hcl, HCL_ESYSMEM); | 
					
						
							|  |  |  | 			return HCL_NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		mdp = (hcl_mod_data_t*)HCL_RBT_VPTR(pair); | 
					
						
							| 
									
										
										
										
											2018-02-12 16:51:38 +00:00
										 |  |  | 		if (load(hcl, &mdp->mod) <= -1) | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			hcl_rbt_delete (&hcl->modtab, (hcl_ooch_t*)name, namelen); | 
					
						
							|  |  |  | 			return HCL_NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		mdp->pair = pair; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		HCL_DEBUG1 (hcl, "Opened a static module [%js]\n", mdp->mod.name); | 
					
						
							|  |  |  | 		return mdp; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	#if !defined(HCL_ENABLE_DYNAMIC_MODULE)
 | 
					
						
							|  |  |  | 		HCL_DEBUG2 (hcl, "Cannot find a static module [%.*js]\n", namelen, name); | 
					
						
							| 
									
										
										
										
											2018-02-12 10:50:44 +00:00
										 |  |  | 		hcl_seterrbfmt (hcl, HCL_ENOENT, "unable to find a static module [%.*js]", namelen, name); | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 		return HCL_NULL; | 
					
						
							|  |  |  | 	#endif
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if !defined(HCL_ENABLE_DYNAMIC_MODULE)
 | 
					
						
							|  |  |  | 	HCL_DEBUG2 (hcl, "Cannot open module [%.*js] - module loading disabled\n", namelen, name); | 
					
						
							| 
									
										
										
										
											2018-02-12 10:50:44 +00:00
										 |  |  | 	hcl_seterrbfmt (hcl, HCL_ENOIMPL, "unable to open module [%.*js] - module loading disabled", namelen, name); | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 	return HCL_NULL; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* attempt to find a dynamic external module */ | 
					
						
							|  |  |  | 	HCL_MEMSET (&md, 0, HCL_SIZEOF(md)); | 
					
						
							| 
									
										
										
										
											2018-04-09 15:54:54 +00:00
										 |  |  | 	md.mod.inctx = hcl->option.mod_inctx; | 
					
						
							| 
									
										
										
										
											2018-04-07 15:54:16 +00:00
										 |  |  | 	hcl_copy_oochars((hcl_ooch_t*)md.mod.name, name, namelen); | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 	if (hcl->vmprim.dl_open && hcl->vmprim.dl_getsym && hcl->vmprim.dl_close) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-04-12 02:50:37 +00:00
										 |  |  | 		md.handle = hcl->vmprim.dl_open(hcl, &buf[MOD_PREFIX_LEN], HCL_VMPRIM_DLOPEN_PFMOD); | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (md.handle == HCL_NULL)  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HCL_DEBUG2 (hcl, "Cannot open a module [%.*js]\n", namelen, name); | 
					
						
							| 
									
										
										
										
											2018-02-12 10:50:44 +00:00
										 |  |  | 		hcl_seterrbfmt (hcl, HCL_ENOENT, "unable to open a module [%.*js]", namelen, name); | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 		return HCL_NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* attempt to get hcl_mod_xxx where xxx is the module name*/ | 
					
						
							| 
									
										
										
										
											2018-02-26 15:24:45 +00:00
										 |  |  | 	load = (hcl_mod_load_t)hcl->vmprim.dl_getsym(hcl, md.handle, buf); | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 	if (!load)  | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-02-12 16:51:38 +00:00
										 |  |  | 		hcl_seterrbfmt (hcl, hcl_geterrnum(hcl), "unable to get module symbol [%js] in [%.*js]", buf, namelen, name); | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 		HCL_DEBUG3 (hcl, "Cannot get a module symbol [%js] in [%.*js]\n", buf, namelen, name); | 
					
						
							|  |  |  | 		hcl->vmprim.dl_close (hcl, md.handle); | 
					
						
							|  |  |  | 		return HCL_NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* i copy-insert 'md' into the table before calling 'load'.
 | 
					
						
							|  |  |  | 	 * to pass the same address to load(), query(), etc */ | 
					
						
							| 
									
										
										
										
											2018-02-12 16:51:38 +00:00
										 |  |  | 	pair = hcl_rbt_insert(&hcl->modtab, (void*)name, namelen, &md, HCL_SIZEOF(md)); | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 	if (pair == HCL_NULL) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HCL_DEBUG2 (hcl, "Cannot register a module [%.*js]\n", namelen, name); | 
					
						
							| 
									
										
										
										
											2018-02-12 10:50:44 +00:00
										 |  |  | 		hcl_seterrbfmt (hcl, HCL_ESYSMEM, "unable to register a module [%.*js] for memory shortage", namelen, name); | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 		hcl->vmprim.dl_close (hcl, md.handle); | 
					
						
							|  |  |  | 		return HCL_NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mdp = (hcl_mod_data_t*)HCL_RBT_VPTR(pair); | 
					
						
							| 
									
										
										
										
											2018-02-12 16:51:38 +00:00
										 |  |  | 	if (load(hcl, &mdp->mod) <= -1) | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-02-12 10:50:44 +00:00
										 |  |  | 		const hcl_ooch_t* oldmsg = hcl_backuperrmsg (hcl); | 
					
						
							|  |  |  | 		hcl_seterrbfmt (hcl, hcl_geterrnum(hcl), "module initializer [%js] returned failure in [%.*js] - %js", buf, namelen, name, oldmsg);  | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 		HCL_DEBUG3 (hcl, "Module function [%js] returned failure in [%.*js]\n", buf, namelen, name); | 
					
						
							|  |  |  | 		hcl_rbt_delete (&hcl->modtab, name, namelen); | 
					
						
							|  |  |  | 		hcl->vmprim.dl_close (hcl, mdp->handle); | 
					
						
							|  |  |  | 		return HCL_NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mdp->pair = pair; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HCL_DEBUG2 (hcl, "Opened a module [%js] - %p\n", mdp->mod.name, mdp->handle); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* the module loader must ensure to set a proper query handler */ | 
					
						
							|  |  |  | 	HCL_ASSERT (hcl, mdp->mod.query != HCL_NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return mdp; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void hcl_closemod (hcl_t* hcl, hcl_mod_data_t* mdp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (mdp->mod.unload) mdp->mod.unload (hcl, &mdp->mod); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (mdp->handle)  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		hcl->vmprim.dl_close (hcl, mdp->handle); | 
					
						
							|  |  |  | 		HCL_DEBUG2 (hcl, "Closed a module [%js] - %p\n", mdp->mod.name, mdp->handle); | 
					
						
							|  |  |  | 		mdp->handle = HCL_NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HCL_DEBUG1 (hcl, "Closed a static module [%js]\n", mdp->mod.name); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (mdp->pair) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/*mdp->pair = HCL_NULL;*/ /* this reset isn't needed as the area will get freed by hcl_rbt_delete()) */ | 
					
						
							| 
									
										
										
										
											2018-04-07 15:54:16 +00:00
										 |  |  | 		hcl_rbt_delete (&hcl->modtab, mdp->mod.name, hcl_count_oocstr(mdp->mod.name)); | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-28 04:52:01 +00:00
										 |  |  | hcl_pfbase_t* hcl_querymod (hcl_t* hcl, const hcl_ooch_t* pfid, hcl_oow_t pfidlen, hcl_mod_t** mod) | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* primitive function identifier
 | 
					
						
							|  |  |  | 	 *   _funcname | 
					
						
							|  |  |  | 	 *   modname_funcname | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	hcl_rbt_pair_t* pair; | 
					
						
							|  |  |  | 	hcl_mod_data_t* mdp; | 
					
						
							|  |  |  | 	const hcl_ooch_t* sep; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hcl_oow_t mod_name_len; | 
					
						
							|  |  |  | 	hcl_pfbase_t* pfbase; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-09 15:54:54 +00:00
										 |  |  | 	sep = hcl_rfind_oochar(pfid, pfidlen, '.'); | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 	if (!sep) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* i'm writing a conservative code here. the compiler should 
 | 
					
						
							|  |  |  | 		 * guarantee that a period is included in an primitive function identifer. | 
					
						
							|  |  |  | 		 * what if the compiler is broken? imagine a buggy compiler rewritten | 
					
						
							|  |  |  | 		 * in hcl itself? */ | 
					
						
							|  |  |  | 		HCL_DEBUG2 (hcl, "Internal error - no period in a primitive function identifier [%.*js] - buggy compiler?\n", pfidlen, pfid); | 
					
						
							|  |  |  | 		hcl_seterrbfmt (hcl, HCL_EINTERN, "no period in a primitive function identifier [%.*js]", pfidlen, pfid); | 
					
						
							|  |  |  | 		return HCL_NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mod_name_len = sep - pfid; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* the first segment through the segment before the last compose a
 | 
					
						
							|  |  |  | 	 * module id. the last segment is the primitive function name. | 
					
						
							|  |  |  | 	 * for instance, in con.window.open, con.window is a module id and | 
					
						
							|  |  |  | 	 * open is the primitive function name. */ | 
					
						
							| 
									
										
										
										
											2018-02-28 04:52:01 +00:00
										 |  |  | 	pair = hcl_rbt_search(&hcl->modtab, pfid, mod_name_len); | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 	if (pair) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		mdp = (hcl_mod_data_t*)HCL_RBT_VPTR(pair); | 
					
						
							|  |  |  | 		HCL_ASSERT (hcl, mdp != HCL_NULL); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* open a module using the part before the last period */ | 
					
						
							| 
									
										
										
										
											2018-02-28 04:52:01 +00:00
										 |  |  | 		mdp = hcl_openmod(hcl, pfid, mod_name_len); | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 		if (!mdp) return HCL_NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-28 04:52:01 +00:00
										 |  |  | 	if ((pfbase = mdp->mod.query(hcl, &mdp->mod, sep + 1, pfidlen - mod_name_len - 1)) == HCL_NULL)  | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		/* the primitive function is not found. but keep the module open even if it's opened above */ | 
					
						
							|  |  |  | 		HCL_DEBUG3 (hcl, "Cannot find a primitive function [%.*js] in a module [%js]\n", pfidlen - mod_name_len - 1, sep + 1, mdp->mod.name); | 
					
						
							|  |  |  | 		hcl_seterrbfmt (hcl, HCL_ENOENT, "unable to find a primitive function [%.*js] in a module [%js]", pfidlen - mod_name_len - 1, sep + 1, mdp->mod.name); | 
					
						
							|  |  |  | 		return HCL_NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-28 04:52:01 +00:00
										 |  |  | 	*mod = &mdp->mod; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-09 04:24:50 +00:00
										 |  |  | 	HCL_DEBUG4 (hcl, "Found a primitive function [%.*js] in a module [%js] - %p\n", | 
					
						
							|  |  |  | 		pfidlen - mod_name_len - 1, sep + 1, mdp->mod.name, pfbase); | 
					
						
							|  |  |  | 	return pfbase; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-12 16:51:38 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | hcl_pfbase_t* hcl_findpfbase (hcl_t* hcl, hcl_pfinfo_t* pfinfo, hcl_oow_t pfcount, const hcl_ooch_t* name, hcl_oow_t namelen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* binary search */ | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | 	/* [NOTE] this algorithm is NOT underflow safe with hcl_oow_t types */ | 
					
						
							|  |  |  | 	int left, right, mid; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (left = 0, right = pfcount - 1; left <= right; ) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/*mid = (left + right) / 2;*/ | 
					
						
							|  |  |  | 		mid = left + ((right - left) / 2); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-07 15:54:16 +00:00
										 |  |  | 		n = hcl_comp_oochars_oocstr (name, namelen, pfinfo[mid].mthname); | 
					
						
							| 
									
										
										
										
											2018-02-12 16:51:38 +00:00
										 |  |  | 		if (n < 0) right = mid - 1; /* this substraction can make right negative. so i can't use hcl_oow_t for the variable */ | 
					
						
							|  |  |  | 		else if (n > 0) left = mid + 1; | 
					
						
							|  |  |  | 		else return &pfinfo[mid].base; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	/* [NOTE] this algorithm is underflow safe with hcl_oow_t types */ | 
					
						
							|  |  |  | 	hcl_oow_t base, mid, lim; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (base = 0, lim = pfcount; lim > 0; lim >>= 1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		mid = base + (lim >> 1); | 
					
						
							| 
									
										
										
										
											2018-04-07 15:54:16 +00:00
										 |  |  | 		n = hcl_comp_oochars_oocstr (name, namelen, pfinfo[mid].mthname); | 
					
						
							| 
									
										
										
										
											2018-02-12 16:51:38 +00:00
										 |  |  | 		if (n == 0) return &pfinfo[mid].base; | 
					
						
							|  |  |  | 		if (n > 0) { base = mid + 1; lim--; } | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hcl_seterrnum (hcl, HCL_ENOENT); | 
					
						
							|  |  |  | 	return HCL_NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 |