1011 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1011 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|     Copyright (c) 2016-2018 Chung, Hyung-Hwan. All rights reserved.
 | |
| 
 | |
|     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 "hak-prv.h"
 | |
| 
 | |
| 
 | |
| #include <stdio.h>
 | |
| #define PRINT_STACK_ALIGN 128
 | |
| 
 | |
| enum
 | |
| {
 | |
| 	PRINT_STACK_CONS,
 | |
| 	PRINT_STACK_ARRAY,
 | |
| 	PRINT_STACK_ARRAY_END,
 | |
| 	PRINT_STACK_DIC,
 | |
| 	PRINT_STACK_DIC_END
 | |
| };
 | |
| 
 | |
| typedef struct print_stack_t print_stack_t;
 | |
| struct print_stack_t
 | |
| {
 | |
| 	int type;
 | |
| 	hak_oop_t obj;
 | |
| 	hak_oop_t obj2;
 | |
| 	hak_oow_t idx;
 | |
| 	hak_oow_t idx2;
 | |
| };
 | |
| 
 | |
| static HAK_INLINE int push (hak_t* hak, print_stack_t* info)
 | |
| {
 | |
| 	if (hak->p.s.size >= hak->p.s.capa)
 | |
| 	{
 | |
| 		print_stack_t* tmp;
 | |
| 		hak_oow_t new_capa;
 | |
| 
 | |
| 		new_capa = HAK_ALIGN (hak->p.s.capa + 1, PRINT_STACK_ALIGN);
 | |
| 		tmp = (print_stack_t*)hak_reallocmem(hak, hak->p.s.ptr, new_capa * HAK_SIZEOF(*info));
 | |
| 		if (!tmp) return -1;
 | |
| 
 | |
| 		hak->p.s.ptr = tmp;
 | |
| 		hak->p.s.capa = new_capa;
 | |
| 	}
 | |
| 
 | |
| 	((print_stack_t*)hak->p.s.ptr)[hak->p.s.size] = *info;
 | |
| 	hak->p.s.size++;
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static HAK_INLINE void pop (hak_t* hak, print_stack_t* info)
 | |
| {
 | |
| 	HAK_ASSERT(hak, hak->p.s.size > 0);
 | |
| 	hak->p.s.size--;
 | |
| 	*info = ((print_stack_t*)hak->p.s.ptr)[hak->p.s.size];
 | |
| }
 | |
| 
 | |
| enum
 | |
| {
 | |
| 	WORD_UNDEF,
 | |
| 	WORD_NIL,
 | |
| 	WORD_TRUE,
 | |
| 	WORD_FALSE,
 | |
| 
 | |
| 	WORD_SET,
 | |
| 	WORD_PRIM,
 | |
| 
 | |
| 	WORD_FUNCTION,
 | |
| 	WORD_BLOCK,
 | |
| 	WORD_CONTEXT,
 | |
| 	WORD_PROCESS,
 | |
| 	WORD_PROCESS_SCHEDULER,
 | |
| 	WORD_SEMAPHORE,
 | |
| 	WORD_SEMAPHORE_GROUP,
 | |
| 	WORD_CLASS,
 | |
| 	WORD_INSTANCE
 | |
| };
 | |
| 
 | |
| static struct
 | |
| {
 | |
| 	hak_oow_t  len;
 | |
| 	hak_ooch_t ptr[20];
 | |
| } word[] =
 | |
| {
 | |
| 	{  8,  { '#','<','U','N','D','E','F','>' } },
 | |
| 	{  3,  { 'n','i','l' } },
 | |
| 	{  4,  { 't','r','u','e' } },
 | |
| 	{  5,  { 'f','a','l','s','e' } },
 | |
| 
 | |
| 	{  6,  { '#','<','S','E','T','>' } },
 | |
| 	{  7,  { '#','<','P','R','I','M','>' } },
 | |
| 
 | |
| 	{  11, { '#','<','F','U','N','C','T','I','O','N','>' } },
 | |
| 	{  8,  { '#','<','B','L','O','C','K','>' } },
 | |
| 	{  10, { '#','<','C','O','N','T','E','X','T','>' } },
 | |
| 	{  10, { '#','<','P','R','O','C','E','S','S','>' } },
 | |
| 	{  20, { '#','<','P','R','O','C','E','S','S','-','S','C','H','E','D','U','L','E','R','>' } },
 | |
| 	{  12, { '#','<','S','E','M','A','P','H','O','R','E','>' } },
 | |
| 	{  18, { '#','<','S','E','M','A','P','H','O','R','E','-','G','R','O','U','P','>' } },
 | |
| 
 | |
| 	{  8,  { '#','<','C','L','A','S','S','>' } },
 | |
| 	{  11, { '#','<','I','N','S','T','A','N','C','E','>' } }
 | |
| };
 | |
| 
 | |
| static HAK_INLINE int print_single_char (hak_t* hak, hak_fmtout_t* fmtout, hak_ooch_t ch)
 | |
| {
 | |
| 	hak_oochu_t chu = (hak_oochu_t)ch;
 | |
| 	if (chu == '\\' || chu == '\"')
 | |
| 	{
 | |
| 		if (hak_bfmt_out(hak, fmtout, "\\%jc", chu) <= -1) return -1;
 | |
| 	}
 | |
| #if defined(HAK_OOCH_IS_UCH)
 | |
| 	else if (chu < ' ')
 | |
| #else
 | |
| 	else if (chu < ' ' || chu >= 0x80)
 | |
| #endif
 | |
| 	{
 | |
| 		hak_oochu_t escaped;
 | |
| 
 | |
| 		switch (chu)
 | |
| 		{
 | |
| 			case '\0':
 | |
| 				escaped = '0';
 | |
| 				break;
 | |
| 			case '\n':
 | |
| 				escaped = 'n';
 | |
| 				break;
 | |
| 			case '\r':
 | |
| 				escaped = 'r';
 | |
| 				break;
 | |
| 			case '\t':
 | |
| 				escaped = 't';
 | |
| 				break;
 | |
| 			case '\f':
 | |
| 				escaped = 'f';
 | |
| 				break;
 | |
| 			case '\b':
 | |
| 				escaped = 'b';
 | |
| 				break;
 | |
| 			case '\v':
 | |
| 				escaped = 'v';
 | |
| 				break;
 | |
| 			case '\a':
 | |
| 				escaped = 'a';
 | |
| 				break;
 | |
| 			default:
 | |
| 				escaped = chu;
 | |
| 				break;
 | |
| 		}
 | |
| 
 | |
| 		if (escaped == chu)
 | |
| 		{
 | |
| 		#if (HAK_SIZEOF_OOCH_T >= 4)
 | |
| 			if (chu >= 0x10000u)
 | |
| 			{
 | |
| 				if (hak_bfmt_out(hak, fmtout, "\\U%08X", chu) <= -1) return -1;
 | |
| 			}
 | |
| 			else
 | |
| 		#endif
 | |
| 			{
 | |
| 		#if (HAK_SIZEOF_OOCH_T >= 2)
 | |
| 				if (chu >= 0x100u)
 | |
| 				{
 | |
| 					if (hak_bfmt_out(hak, fmtout, "\\u%04X", chu) <= -1) return -1;
 | |
| 				}
 | |
| 				else
 | |
| 		#endif
 | |
| 				{
 | |
| 					if (hak_bfmt_out(hak, fmtout, "\\x%02X", chu) <= -1) return -1;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			if (hak_bfmt_out(hak, fmtout, "\\%jc", escaped) <= -1) return -1;
 | |
| 		}
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		if (hak_bfmt_out(hak, fmtout, "%jc", ch) <= -1) return -1;
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static HAK_INLINE int print_single_byte_char (hak_t* hak, hak_fmtout_t* fmtout, hak_bch_t ch)
 | |
| {
 | |
| 	hak_bchu_t chu = (hak_bchu_t)ch;
 | |
| 	if (chu == '\\' || chu == '\"')
 | |
| 	{
 | |
| 		if (hak_bfmt_out(hak, fmtout, "\\%hc", chu) <= -1) return -1;
 | |
| 	}
 | |
| #if defined(HAK_OOCH_IS_UCH)
 | |
| 	else if (chu < ' ')
 | |
| #else
 | |
| 	else if (chu < ' ' || chu >= 0x80)
 | |
| #endif
 | |
| 	{
 | |
| 		hak_bchu_t escaped;
 | |
| 
 | |
| 		switch (chu)
 | |
| 		{
 | |
| 			case '\0':
 | |
| 				escaped = '0';
 | |
| 				break;
 | |
| 			case '\n':
 | |
| 				escaped = 'n';
 | |
| 				break;
 | |
| 			case '\r':
 | |
| 				escaped = 'r';
 | |
| 				break;
 | |
| 			case '\t':
 | |
| 				escaped = 't';
 | |
| 				break;
 | |
| 			case '\f':
 | |
| 				escaped = 'f';
 | |
| 				break;
 | |
| 			case '\b':
 | |
| 				escaped = 'b';
 | |
| 				break;
 | |
| 			case '\v':
 | |
| 				escaped = 'v';
 | |
| 				break;
 | |
| 			case '\a':
 | |
| 				escaped = 'a';
 | |
| 				break;
 | |
| 			default:
 | |
| 				escaped = chu;
 | |
| 				break;
 | |
| 		}
 | |
| 
 | |
| 		if (escaped == chu)
 | |
| 		{
 | |
| 			if (hak_bfmt_out(hak, fmtout, "\\x%02X", chu) <= -1) return -1;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			if (hak_bfmt_out(hak, fmtout, "\\%hc", escaped) <= -1) return -1;
 | |
| 		}
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		if (hak_bfmt_out(hak, fmtout, "%hc", ch) <= -1) return -1;
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int hak_fmt_object (hak_t* hak, hak_fmtout_t* fmtout, hak_oop_t obj)
 | |
| {
 | |
| 	hak_oop_t cur;
 | |
| 	print_stack_t ps;
 | |
| 	hak_oop_class_t _class;
 | |
| 	int brand;
 | |
| 	int word_index;
 | |
| 	int json;
 | |
| 
 | |
| 	static const hak_bch_t *opening_parens[][2] =
 | |
| 	{
 | |
| 		                            /* navtive   json */
 | |
| 		HAK_AID(HAK_CONCODE_XLIST)     { "(",     "(" },
 | |
| 		HAK_AID(HAK_CONCODE_MLIST)     { "(",     "(" },
 | |
| 		HAK_AID(HAK_CONCODE_ALIST)     { "(",     "(" },
 | |
| 		HAK_AID(HAK_CONCODE_BLIST)     { "(",     "(" },
 | |
| 		HAK_AID(HAK_CONCODE_BLOCK)     { "{",     "{" },
 | |
| 		HAK_AID(HAK_CONCODE_ARRAY)     { "#[",    "[" },
 | |
| 		HAK_AID(HAK_CONCODE_BYTEARRAY) { "#b[",   "[" },
 | |
| 		HAK_AID(HAK_CONCODE_CHARARRAY) { "#c[",   "[" },
 | |
| 		HAK_AID(HAK_CONCODE_DIC)       { "#{",    "{" },
 | |
| 		HAK_AID(HAK_CONCODE_QLIST)     { "#(",    "[" },
 | |
| 		HAK_AID(HAK_CONCODE_TUPLE)     { "[",     "[" }
 | |
| 	};
 | |
| 
 | |
| 	static const hak_bch_t *closing_parens[][2] =
 | |
| 	{
 | |
| 		HAK_AID(HAK_CONCODE_XLIST)     { ")",     ")" },
 | |
| 		HAK_AID(HAK_CONCODE_MLIST)     { ")",     ")" },
 | |
| 		HAK_AID(HAK_CONCODE_ALIST)     { ")",     ")" },
 | |
| 		HAK_AID(HAK_CONCODE_BLIST)     { ")",     ")" },
 | |
| 		HAK_AID(HAK_CONCODE_BLOCK)     { "}",     "}" },
 | |
| 		HAK_AID(HAK_CONCODE_ARRAY)     { "]",     "]" },
 | |
| 		HAK_AID(HAK_CONCODE_BYTEARRAY) { "]",     "]" },
 | |
| 		HAK_AID(HAK_CONCODE_CHARARRAY) { "]",     "]" },
 | |
| 		HAK_AID(HAK_CONCODE_DIC)       { "}",     "}" },
 | |
| 		HAK_AID(HAK_CONCODE_QLIST)     { ")",     "]" },
 | |
| 		HAK_AID(HAK_CONCODE_TUPLE)     { "]",     "]" }
 | |
| 	};
 | |
| 
 | |
| 	static const hak_bch_t* breakers[][2] =
 | |
| 	{
 | |
| 		{ " ",       "," }, /* item breaker */
 | |
| 		{ " ",       ":" }  /* key value breaker */
 | |
| 	};
 | |
| 
 | |
| 	json = !!(fmtout->mask & HAK_LOG_PREFER_JSON);
 | |
| 
 | |
| next:
 | |
| 	_class = (hak_oop_class_t)HAK_CLASSOF(hak, obj);
 | |
| 	brand = HAK_OOP_TO_SMOOI(_class->ibrand);
 | |
| 	switch (brand)
 | |
| 	{
 | |
| 		case HAK_BRAND_SMOOI:
 | |
| 			if (hak_bfmt_out(hak, fmtout, "%zd", HAK_OOP_TO_SMOOI(obj)) <= -1) return -1;
 | |
| 			goto done;
 | |
| 
 | |
| 		case HAK_BRAND_SMPTR:
 | |
| 			if (hak_bfmt_out(hak, fmtout, "#p%zX", (hak_oow_t)HAK_OOP_TO_SMPTR(obj)) <= -1) return -1;
 | |
| 			goto done;
 | |
| 
 | |
| 		case HAK_BRAND_ERROR:
 | |
| 			if (hak_bfmt_out(hak, fmtout, "#e%zd", (hak_ooi_t)HAK_OOP_TO_ERROR(obj)) <= -1) return -1;
 | |
| 			goto done;
 | |
| 
 | |
| 		case HAK_BRAND_CHARACTER:
 | |
| 		{
 | |
| 			hak_ooch_t ch = HAK_OOP_TO_CHAR(obj);
 | |
| 			if (hak_bfmt_out(hak, fmtout, "\'") <= -1 ||
 | |
| 			    print_single_char(hak, fmtout, ch) <= -1 ||
 | |
| 			    hak_bfmt_out(hak, fmtout, "\'") <= -1) return -1;
 | |
| 			goto done;
 | |
| 		}
 | |
| 
 | |
| 		case HAK_BRAND_UNDEF:
 | |
| 			word_index = WORD_UNDEF;
 | |
| 			goto print_word;
 | |
| 
 | |
| 		case HAK_BRAND_NIL:
 | |
| 			word_index = WORD_NIL;
 | |
| 			goto print_word;
 | |
| 
 | |
| 		case HAK_BRAND_TRUE:
 | |
| 			word_index = WORD_TRUE;
 | |
| 			goto print_word;
 | |
| 
 | |
| 		case HAK_BRAND_FALSE:
 | |
| 			word_index = WORD_FALSE;
 | |
| 			goto print_word;
 | |
| 
 | |
| 		case HAK_BRAND_PBIGINT:
 | |
| 		case HAK_BRAND_NBIGINT:
 | |
| 		{
 | |
| 			hak_oop_t tmp;
 | |
| 
 | |
| 			/* -1 to drive hak_inttostr() to not create a new string object.
 | |
| 			 * not using the object memory. the result stays in the temporary
 | |
| 			 * buffer */
 | |
| 			tmp = hak_inttostr(hak, obj, 10 | HAK_INTTOSTR_NONEWOBJ);
 | |
| 			if (!tmp) return -1;
 | |
| 
 | |
| 			HAK_ASSERT(hak, (hak_oop_t)tmp == hak->_nil);
 | |
| 			if (hak_bfmt_out(hak, fmtout, "%.*js", hak->inttostr.xbuf.len, hak->inttostr.xbuf.ptr) <= -1) return -1;
 | |
| 			break;
 | |
| 		}
 | |
| 
 | |
| 		case HAK_BRAND_FPDEC:
 | |
| 		{
 | |
| 			hak_oop_fpdec_t f = (hak_oop_fpdec_t)obj;
 | |
| 			hak_ooi_t scale;
 | |
| 
 | |
| 			scale = HAK_OOP_TO_SMOOI(f->scale);
 | |
| 
 | |
| 			if (f->value == HAK_SMOOI_TO_OOP(0))
 | |
| 			{
 | |
| 				if (scale == 0)
 | |
| 				{
 | |
| 					if (hak_bfmt_out(hak, fmtout, "0.") <= -1) return -1;
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 					if (hak_bfmt_out(hak, fmtout, "0.%0*d", scale, 0) <= -1) return -1;
 | |
| 				}
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				hak_oop_t tmp;
 | |
| 				hak_oow_t len, adj;
 | |
| 
 | |
| 				tmp = hak_inttostr(hak, f->value, 10 | HAK_INTTOSTR_NONEWOBJ);
 | |
| 				if (!tmp) return -1;
 | |
| 
 | |
| 				adj = (hak->inttostr.xbuf.ptr[0] == '-');
 | |
| 				len = hak->inttostr.xbuf.len - adj;
 | |
| 
 | |
| 				if (len <= scale)
 | |
| 				{
 | |
| 					if (scale == len)
 | |
| 					{
 | |
| 						if (hak_bfmt_out(hak, fmtout, "%.*js0.%.*js",
 | |
| 							adj, hak->inttostr.xbuf.ptr,
 | |
| 							len, &hak->inttostr.xbuf.ptr[adj]) <= -1) return -1;
 | |
| 					}
 | |
| 					else
 | |
| 					{
 | |
| 						if (hak_bfmt_out(hak, fmtout, "%.*js0.%0*d%.*js",
 | |
| 							adj, hak->inttostr.xbuf.ptr,
 | |
| 							scale - len, 0,
 | |
| 							len, &hak->inttostr.xbuf.ptr[adj]) <= -1) return -1;
 | |
| 					}
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 					hak_ooi_t ndigits;
 | |
| 					ndigits = hak->inttostr.xbuf.len - scale;
 | |
| 					if (hak_bfmt_out(hak, fmtout, "%.*js.%.*js", ndigits, hak->inttostr.xbuf.ptr, scale, &hak->inttostr.xbuf.ptr[ndigits]) <= -1) return -1;
 | |
| 				}
 | |
| 			}
 | |
| 			break;
 | |
| 		}
 | |
| 
 | |
| #if 0
 | |
| 		case HAK_BRAND_REAL:
 | |
| 		{
 | |
| 			qse_char_t buf[256];
 | |
| 			hak->prm.sprintf (
 | |
| 				hak->prm.ctx,
 | |
| 				buf, HAK_COUNTOF(buf),
 | |
| 				HAK_T("%Lf"),
 | |
| 			#ifdef __MINGW32__
 | |
| 				(double)HAK_RVAL(obj)
 | |
| 			#else
 | |
| 				(long double)HAK_RVAL(obj)
 | |
| 			#endif
 | |
| 			);
 | |
| 
 | |
| 			OUTPUT_STR(hak, buf);
 | |
| 			break;
 | |
| 		}
 | |
| #endif
 | |
| 
 | |
| 		case HAK_BRAND_SYMBOL:
 | |
| 			/* Any needs for special action if SYNT(obj) is true?
 | |
| 			 * I simply treat the syntax symbol as a normal symbol
 | |
| 			 * for printing currently. */
 | |
| 			/* TODO: escaping if needed */
 | |
| 			/*if (hak_bfmt_out(hak, fmtout, "#\"%.*js\"", HAK_OBJ_GET_SIZE(obj), HAK_OBJ_GET_CHAR_SLOT(obj)) <= -1) return -1;*/
 | |
| 			if (hak_bfmt_out(hak, fmtout, "%.*js", HAK_OBJ_GET_SIZE(obj), HAK_OBJ_GET_CHAR_SLOT(obj)) <= -1) return -1;
 | |
| 			break;
 | |
| 
 | |
| 		case HAK_BRAND_STRING:
 | |
| 		{
 | |
| 			hak_ooch_t ch;
 | |
| 			hak_oow_t i;
 | |
| 			int escape = 0;
 | |
| 
 | |
| 			for (i = 0; i < HAK_OBJ_GET_SIZE(obj); i++)
 | |
| 			{
 | |
| 				ch = ((hak_oop_char_t)obj)->slot[i];
 | |
| 				if (ch < ' ' || ch == '\"' || ch == '\\')
 | |
| 				{
 | |
| 					escape = 1;
 | |
| 					break;
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			if (escape)
 | |
| 			{
 | |
| 				if (hak_bfmt_out(hak, fmtout, "\"") <= -1) return -1;
 | |
| 				for (i = 0; i < HAK_OBJ_GET_SIZE(obj); i++)
 | |
| 				{
 | |
| 					ch = ((hak_oop_char_t)obj)->slot[i];
 | |
| 					if (print_single_char(hak, fmtout, ch) <= -1) return -1;
 | |
| 				}
 | |
| 				if (hak_bfmt_out(hak, fmtout, "\"") <= -1) return -1;
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				if (hak_bfmt_out(hak, fmtout, "\"%.*js\"", HAK_OBJ_GET_SIZE(obj), HAK_OBJ_GET_CHAR_SLOT(obj)) <= -1) return -1;
 | |
| 			}
 | |
| 			break;
 | |
| 		}
 | |
| 
 | |
| 		case HAK_BRAND_BYTE_STRING:
 | |
| 		{
 | |
| 			hak_bch_t ch;
 | |
| 			hak_oow_t i;
 | |
| 			int escape = 0;
 | |
| 
 | |
| 			for (i = 0; i < HAK_OBJ_GET_SIZE(obj); i++)
 | |
| 			{
 | |
| 				ch = ((hak_oop_byte_t)obj)->slot[i];
 | |
| 				if (ch < ' ' || ch == '\"' || ch == '\\')
 | |
| 				{
 | |
| 					escape = 1;
 | |
| 					break;
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			if (escape)
 | |
| 			{
 | |
| 				if (hak_bfmt_out(hak, fmtout, "b\"") <= -1) return -1;
 | |
| 				for (i = 0; i < HAK_OBJ_GET_SIZE(obj); i++)
 | |
| 				{
 | |
| 					ch = ((hak_oop_byte_t)obj)->slot[i];
 | |
| 					if (print_single_byte_char(hak, fmtout, ch) <= -1) return -1;
 | |
| 				}
 | |
| 				if (hak_bfmt_out(hak, fmtout, "\"") <= -1) return -1;
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				if (hak_bfmt_out(hak, fmtout, "b\"%.*hs\"", HAK_OBJ_GET_SIZE(obj), HAK_OBJ_GET_BYTE_SLOT(obj)) <= -1) return -1;
 | |
| 			}
 | |
| 			break;
 | |
| 		}
 | |
| 
 | |
| 
 | |
| 		case HAK_BRAND_CONS:
 | |
| 		{
 | |
| 			int concode;
 | |
| 
 | |
| 			/* this part is to print a linked list of cells. ignore the
 | |
| 			 * request to output in the json format */
 | |
| 
 | |
| 			concode = HAK_OBJ_GET_FLAGS_CONCODE(obj);
 | |
| 			if (hak_bfmt_out(hak, fmtout, opening_parens[concode][0]) <= -1) return -1;
 | |
| 			cur = obj;
 | |
| 
 | |
| 			/* TODO: for MLIST, print : after the first element.
 | |
| 			 *       for ALIST, print := after the first element */
 | |
| 			do
 | |
| 			{
 | |
| 				int x;
 | |
| 
 | |
| 				/* Push what to print next on to the stack
 | |
| 				 * the variable p is */
 | |
| 				ps.type = PRINT_STACK_CONS;
 | |
| 				ps.obj = HAK_CONS_CDR(cur);
 | |
| 				ps.idx = concode; /* this is not an index but use this field to restore concode */
 | |
| 				x = push(hak, &ps);
 | |
| 				if (x <= -1) return -1;
 | |
| 
 | |
| 				obj = HAK_CONS_CAR(cur);
 | |
| 				/* Jump to the 'next' label so that the object
 | |
| 				 * pointed to by 'obj' is printed. Once it
 | |
| 				 * ends, a jump back to the 'resume' label
 | |
| 				 * is made at the at of this function. */
 | |
| 				goto next;
 | |
| 
 | |
| 			resume_cons:
 | |
| 				HAK_ASSERT(hak, ps.type == PRINT_STACK_CONS);
 | |
| 				cur = ps.obj; /* Get back the CDR pushed */
 | |
| 				concode = ps.idx; /* restore the concode */
 | |
| 				if (HAK_IS_NIL(hak,cur))
 | |
| 				{
 | |
| 					/* The CDR part points to a NIL object, which
 | |
| 					 * indicates the end of a list. break the loop */
 | |
| 					break;
 | |
| 				}
 | |
| 				if (!HAK_OOP_IS_POINTER(cur) || HAK_OBJ_GET_CLASS(cur) != (hak_oop_t)hak->c_cons)
 | |
| 				{
 | |
| 					/* The CDR part does not point to a pair. */
 | |
| 					if (hak_bfmt_out(hak, fmtout, " . ") <= -1) return -1;
 | |
| 
 | |
| 					/* Push NIL so that the HAK_IS_NIL(hak,p) test in
 | |
| 					 * the 'if' statement above breaks the loop
 | |
| 					 * after the jump is maded back to the 'resume'
 | |
| 					 * label. */
 | |
| 					ps.type = PRINT_STACK_CONS;
 | |
| 					ps.obj = hak->_nil;
 | |
| 					x = push(hak, &ps);
 | |
| 					if (x <= -1) return -1;
 | |
| 
 | |
| 					/* Make a jump to 'next' to print the CDR part */
 | |
| 					obj = cur;
 | |
| 					goto next;
 | |
| 				}
 | |
| 
 | |
| 				/* The CDR part points to a pair. proceed to it */
 | |
| 				if (hak_bfmt_out(hak, fmtout, breakers[0][0]) <= -1) return -1;
 | |
| 			}
 | |
| 			while (1);
 | |
| 
 | |
| 			if (hak_bfmt_out(hak, fmtout, closing_parens[concode][0]) <= -1) return -1;
 | |
| 			break;
 | |
| 		}
 | |
| 
 | |
| 		case HAK_BRAND_ARRAY:
 | |
| 		{
 | |
| 			hak_oow_t arridx;
 | |
| 
 | |
| 			if (hak_bfmt_out(hak, fmtout, opening_parens[HAK_CONCODE_ARRAY][json]) <= -1) return -1;
 | |
| 
 | |
| 			if (HAK_OBJ_GET_SIZE(obj) <= 0)
 | |
| 			{
 | |
| 				if (hak_bfmt_out(hak, fmtout, closing_parens[HAK_CONCODE_ARRAY][json]) <= -1) return -1;
 | |
| 				break;
 | |
| 			}
 | |
| 			arridx = 0;
 | |
| 			ps.type = PRINT_STACK_ARRAY;
 | |
| 
 | |
| 			do
 | |
| 			{
 | |
| 				int x;
 | |
| 
 | |
| 				/* Push what to print next on to the stack */
 | |
| 				ps.idx = arridx + 1;
 | |
| 				if (ps.idx >= HAK_OBJ_GET_SIZE(obj))
 | |
| 				{
 | |
| 					ps.type = PRINT_STACK_ARRAY_END;
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 					HAK_ASSERT(hak, ps.type == PRINT_STACK_ARRAY);
 | |
| 					ps.obj = obj;
 | |
| 				}
 | |
| 
 | |
| 				x = push(hak, &ps);
 | |
| 				if (x <= -1) return -1;
 | |
| 
 | |
| 				obj = ((hak_oop_oop_t)obj)->slot[arridx];
 | |
| 				if (arridx > 0)
 | |
| 				{
 | |
| 					if (hak_bfmt_out(hak, fmtout, breakers[0][json]) <= -1) return -1;
 | |
| 				}
 | |
| 				/* Jump to the 'next' label so that the object
 | |
| 				 * pointed to by 'obj' is printed. Once it
 | |
| 				 * ends, a jump back to the 'resume' label
 | |
| 				 * is made at the end of this function. */
 | |
| 				goto next;
 | |
| 
 | |
| 			resume_array:
 | |
| 				HAK_ASSERT(hak, ps.type == PRINT_STACK_ARRAY);
 | |
| 				arridx = ps.idx;
 | |
| 				obj = ps.obj;
 | |
| 			}
 | |
| 			while (1);
 | |
| 			break;
 | |
| 		}
 | |
| 
 | |
| 		case HAK_BRAND_BYTE_ARRAY:
 | |
| 		{
 | |
| 			hak_oow_t i;
 | |
| 			if (hak_bfmt_out(hak, fmtout, opening_parens[HAK_CONCODE_BYTEARRAY][json]) <= -1) return -1;
 | |
| 			if (HAK_OBJ_GET_SIZE(obj) > 0)
 | |
| 			{
 | |
| 				if (hak_bfmt_out(hak, fmtout, "%d", ((hak_oop_byte_t)obj)->slot[0]) <= -1) return -1;
 | |
| 				for (i = 1; i < HAK_OBJ_GET_SIZE(obj); i++)
 | |
| 				{
 | |
| 					if (hak_bfmt_out(hak, fmtout, "%hs%d", breakers[0][json], ((hak_oop_byte_t)obj)->slot[i]) <= -1) return -1;
 | |
| 				}
 | |
| 			}
 | |
| 			if (hak_bfmt_out(hak, fmtout, closing_parens[HAK_CONCODE_BYTEARRAY][json]) <= -1) return -1;
 | |
| 			break;
 | |
| 		}
 | |
| 
 | |
| 		case HAK_BRAND_CHARACTER_ARRAY:
 | |
| 		{
 | |
| 			hak_oow_t i;
 | |
| 			if (hak_bfmt_out(hak, fmtout, opening_parens[HAK_CONCODE_CHARARRAY][json]) <= -1) return -1;
 | |
| 			if (HAK_OBJ_GET_SIZE(obj) > 0)
 | |
| 			{
 | |
| 				if (hak_bfmt_out(hak, fmtout, "'%jc'", ((hak_oop_char_t)obj)->slot[0]) <= -1) return -1;
 | |
| 				for (i = 1; i < HAK_OBJ_GET_SIZE(obj); i++)
 | |
| 				{
 | |
| 					if (hak_bfmt_out(hak, fmtout, "%hs'%jc'", breakers[0][json], ((hak_oop_char_t)obj)->slot[i]) <= -1) return -1;
 | |
| 				}
 | |
| 			}
 | |
| 			if (hak_bfmt_out(hak, fmtout, closing_parens[HAK_CONCODE_CHARARRAY][json]) <= -1) return -1;
 | |
| 			break;
 | |
| 		}
 | |
| 
 | |
| 		case HAK_BRAND_DIC:
 | |
| 		{
 | |
| 			hak_oow_t bucidx, bucsize, buctally;
 | |
| 			hak_oop_dic_t dic;
 | |
| 
 | |
| 			if (hak_bfmt_out(hak, fmtout, opening_parens[HAK_CONCODE_DIC][json]) <= -1) return -1;
 | |
| 
 | |
| 			dic = (hak_oop_dic_t)obj;
 | |
| 			HAK_ASSERT(hak, HAK_OOP_IS_SMOOI(dic->tally));
 | |
| 			if (HAK_OOP_TO_SMOOI(dic->tally) <= 0)
 | |
| 			{
 | |
| 				if (hak_bfmt_out(hak, fmtout, closing_parens[HAK_CONCODE_DIC][json]) <= -1) return -1;
 | |
| 				break;
 | |
| 			}
 | |
| 			bucidx = 0;
 | |
| 			bucsize = HAK_OBJ_GET_SIZE(dic->bucket);
 | |
| 			buctally = 0;
 | |
| 			ps.type = PRINT_STACK_DIC;
 | |
| 			ps.obj2 = (hak_oop_t)dic;
 | |
| 
 | |
| 			do
 | |
| 			{
 | |
| 				int x;
 | |
| 
 | |
| 				if ((buctally & 1) == 0)
 | |
| 				{
 | |
| 					while (bucidx < bucsize)
 | |
| 					{
 | |
| 						/* skip an unoccupied slot in the bucket array */
 | |
| 						obj = dic->bucket->slot[bucidx];
 | |
| 						if (!HAK_IS_NIL(hak,obj)) break;
 | |
| 						bucidx++;
 | |
| 					}
 | |
| 
 | |
| 					if (bucidx >= bucsize)
 | |
| 					{
 | |
| 						/* done. scanned the entire bucket */
 | |
| 						if (hak_bfmt_out(hak, fmtout, closing_parens[HAK_CONCODE_DIC][json]) <= -1) return -1;
 | |
| 						break;
 | |
| 					}
 | |
| 
 | |
| 					ps.idx = bucidx; /* no increment yet */
 | |
| 					HAK_ASSERT(hak, ps.idx < bucsize);
 | |
| 					HAK_ASSERT(hak, ps.type == PRINT_STACK_DIC);
 | |
| 
 | |
| 					ps.obj = dic->bucket->slot[ps.idx];
 | |
| 					ps.idx2 = buctally + 1;
 | |
| 
 | |
| 					x = push(hak, &ps);
 | |
| 					if (x <= -1) return -1;
 | |
| 
 | |
| 					HAK_ASSERT(hak, HAK_IS_CONS(hak,obj));
 | |
| 					obj = HAK_CONS_CAR(obj);
 | |
| 				}
 | |
| 				else
 | |
| 				{
 | |
| 					/* Push what to print next on to the stack */
 | |
| 					ps.idx = bucidx + 1;
 | |
| 					if (ps.idx >= bucsize)
 | |
| 					{
 | |
| 						ps.type = PRINT_STACK_DIC_END;
 | |
| 					}
 | |
| 					else
 | |
| 					{
 | |
| 						HAK_ASSERT(hak, ps.type == PRINT_STACK_DIC);
 | |
| 						ps.obj = dic->bucket->slot[ps.idx];
 | |
| 					}
 | |
| 					ps.idx2 = buctally + 1;
 | |
| 
 | |
| 					x = push(hak, &ps);
 | |
| 					if (x <= -1) return -1;
 | |
| 
 | |
| 					HAK_ASSERT(hak, HAK_IS_CONS(hak,obj));
 | |
| 					obj = HAK_CONS_CDR(obj);
 | |
| 				}
 | |
| 
 | |
| 				if (buctally > 0)
 | |
| 				{
 | |
| 					if (hak_bfmt_out(hak, fmtout, breakers[buctally & 1][json]) <= -1) return -1;
 | |
| 				}
 | |
| 
 | |
| 				/* Jump to the 'next' label so that the object
 | |
| 				 * pointed to by 'obj' is printed. Once it
 | |
| 				 * ends, a jump back to the 'resume' label
 | |
| 				 * is made at the end of this function. */
 | |
| 				goto next;
 | |
| 
 | |
| 			resume_dic:
 | |
| 				HAK_ASSERT(hak, ps.type == PRINT_STACK_DIC);
 | |
| 				bucidx = ps.idx;
 | |
| 				buctally = ps.idx2;
 | |
| 				obj = ps.obj;
 | |
| 				dic = (hak_oop_dic_t)ps.obj2;
 | |
| 				bucsize = HAK_OBJ_GET_SIZE(dic->bucket);
 | |
| 			}
 | |
| 			while (1);
 | |
| 
 | |
| 			break;
 | |
| 		}
 | |
| 
 | |
| 		case HAK_BRAND_PRIM:
 | |
| 			word_index = WORD_PRIM;
 | |
| 			goto print_word;
 | |
| 
 | |
| 		case HAK_BRAND_FUNCTION:
 | |
| 			word_index = WORD_FUNCTION;
 | |
| 			goto print_word;
 | |
| 
 | |
| 		case HAK_BRAND_BLOCK:
 | |
| 			word_index = WORD_BLOCK;
 | |
| 			goto print_word;
 | |
| 
 | |
| 		case HAK_BRAND_CONTEXT:
 | |
| 			word_index = WORD_CONTEXT;
 | |
| 			goto print_word;
 | |
| 
 | |
| 		case HAK_BRAND_PROCESS:
 | |
| 			word_index = WORD_PROCESS;
 | |
| 			goto print_word;
 | |
| 
 | |
| 		case HAK_BRAND_PROCESS_SCHEDULER:
 | |
| 			word_index = WORD_PROCESS_SCHEDULER;
 | |
| 			goto print_word;
 | |
| 
 | |
| 		case HAK_BRAND_SEMAPHORE:
 | |
| 			word_index = WORD_SEMAPHORE;
 | |
| 			goto print_word;
 | |
| 
 | |
| 		case HAK_BRAND_SEMAPHORE_GROUP:
 | |
| 			word_index = WORD_SEMAPHORE_GROUP;
 | |
| 			goto print_word;
 | |
| 
 | |
| 		case HAK_BRAND_CLASS:
 | |
| 		{
 | |
| 			hak_oop_class_t _class = (hak_oop_class_t)obj;
 | |
| 			if (HAK_IS_NIL(hak, _class->name))
 | |
| 			{
 | |
| 				word_index = WORD_CLASS;
 | |
| 				goto print_word;
 | |
| 			}
 | |
| 			HAK_ASSERT(hak, HAK_IS_SYMBOL(hak, _class->name));
 | |
| 			if (hak_bfmt_out(hak, fmtout, "%.*js", HAK_OBJ_GET_SIZE(_class->name), HAK_OBJ_GET_CHAR_SLOT(_class->name)) <= -1) return -1;
 | |
| 			break;
 | |
| 		}
 | |
| 
 | |
| 		case HAK_BRAND_INSTANCE:
 | |
| 		{
 | |
| 			hak_oop_class_t _class = (hak_oop_class_t)HAK_CLASSOF(hak, obj);
 | |
| 			HAK_ASSERT(hak, HAK_IS_CLASS(hak, _class));
 | |
| 			if (HAK_IS_NIL(hak, _class->name))
 | |
| 			{
 | |
| 				word_index = WORD_INSTANCE;
 | |
| 				goto print_word;
 | |
| 			}
 | |
| 			HAK_ASSERT(hak, HAK_IS_SYMBOL(hak, _class->name));
 | |
| 			if (hak_bfmt_out(hak, fmtout, "#INSTANCE OF %.*js", HAK_OBJ_GET_SIZE(_class->name), HAK_OBJ_GET_CHAR_SLOT(_class->name)) <= -1) return -1;
 | |
| 			break;
 | |
| 		}
 | |
| 
 | |
| 		default:
 | |
| 			HAK_DEBUG3 (hak, "Internal error - unknown object brand %d at %s:%d\n", (int)brand, __FILE__, __LINE__);
 | |
| 			HAK_ASSERT(hak, "Unknown object brand" == HAK_NULL);
 | |
| 			hak_seterrbfmt(hak, HAK_EINTERN, "unknown object brand %d", (int)brand);
 | |
| 			return -1;
 | |
| 
 | |
| 		print_word:
 | |
| 			if (hak_bfmt_out(hak, fmtout, "%.*js", word[word_index].len, word[word_index].ptr) <= -1) return -1;
 | |
| 			break;
 | |
| 	}
 | |
| 
 | |
| done:
 | |
| 	/* if the printing stack is not empty, we still got more to print */
 | |
| 	while (hak->p.s.size > 0)
 | |
| 	{
 | |
| 		pop(hak, &ps);
 | |
| 		switch (ps.type)
 | |
| 		{
 | |
| 			case PRINT_STACK_CONS:
 | |
| 				goto resume_cons;
 | |
| 
 | |
| 			case PRINT_STACK_ARRAY:
 | |
| 				goto resume_array;
 | |
| 
 | |
| 			case PRINT_STACK_ARRAY_END:
 | |
| 				if (hak_bfmt_out(hak, fmtout, closing_parens[HAK_CONCODE_ARRAY][json]) <= -1) return -1;
 | |
| 				break;
 | |
| 
 | |
| 			case PRINT_STACK_DIC:
 | |
| 				goto resume_dic;
 | |
| 
 | |
| 			case PRINT_STACK_DIC_END:
 | |
| 				if (hak_bfmt_out(hak, fmtout, closing_parens[HAK_CONCODE_DIC][json]) <= -1) return -1;
 | |
| 				break;
 | |
| 
 | |
| 			default:
 | |
| 				HAK_DEBUG3 (hak, "Internal error - unknown print stack type %d at %s:%d\n", (int)ps.type, __FILE__, __LINE__);
 | |
| 				hak_seterrbfmt(hak, HAK_EINTERN, "internal error - unknown print stack type %d", (int)ps.type);
 | |
| 				return -1;
 | |
| 		}
 | |
| 	}
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| #if 0
 | |
| int hak_outfmtobj (hak_t* hak, hak_bitmask_t mask, hak_oop_t obj, hak_outbfmt_t outbfmt)
 | |
| {
 | |
| 	int n;
 | |
| 
 | |
| 	/* the printer stack must be empty. buggy if not. */
 | |
| 	HAK_ASSERT(hak, hak->p.s.size == 0);
 | |
| 
 | |
| 	hak->p.e = obj; /* remember the head of the object to print */
 | |
| 	n = hak_proutbfmt(hak, mask, obj);
 | |
| 	hak->p.e = hak->_nil; /* reset what's remembered */
 | |
| 
 | |
| 	/* clear the printing stack if an error has occurred for GC not to keep
 | |
| 	 * the objects in the stack */
 | |
| 	if (n <= -1) hak->p.s.size = 0;
 | |
| 
 | |
| 	/* the printer stack must get empty when done. buggy if not */
 | |
| 	HAK_ASSERT(hak, hak->p.s.size == 0);
 | |
| 
 | |
| 	return n;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| int hak_print (hak_t* hak, hak_oop_t obj)
 | |
| {
 | |
| 	HAK_ASSERT(hak, hak->io.udo_wrtr != HAK_NULL);
 | |
| 	/*return hak_outfmtobj(hak, HAK_LOG_APP | HAK_LOG_FATAL, obj);*/
 | |
| 	return hak_prbfmt(hak, "%O", obj);
 | |
| }
 | |
| 
 | |
| void hak_dumpcnode (hak_t* hak, hak_cnode_t* cnode, int newline)
 | |
| {
 | |
| 	int t;
 | |
| 
 | |
| 	/* TODO: this is incomplete function. make it complete */
 | |
| 	if (cnode)
 | |
| 	{
 | |
| 		t = HAK_CNODE_GET_TYPE(cnode);
 | |
| 		switch (t)
 | |
| 		{
 | |
| 			case HAK_CNODE_CHARLIT:
 | |
| 			case HAK_CNODE_BCHRLIT:
 | |
| 			case HAK_CNODE_SYMBOL:
 | |
| 			case HAK_CNODE_DSYMBOL:
 | |
| 			case HAK_CNODE_STRLIT:
 | |
| 			case HAK_CNODE_BSTRLIT:
 | |
| 			case HAK_CNODE_SYMLIT:
 | |
| 			case HAK_CNODE_NUMLIT:
 | |
| 			case HAK_CNODE_RADNUMLIT:
 | |
| 			case HAK_CNODE_FPDECLIT:
 | |
| 			case HAK_CNODE_SMPTRLIT:
 | |
| 			case HAK_CNODE_ERRLIT:
 | |
| 
 | |
| 			case HAK_CNODE_NIL:
 | |
| 			case HAK_CNODE_TRUE:
 | |
| 			case HAK_CNODE_FALSE:
 | |
| 			case HAK_CNODE_SELF:
 | |
| 			case HAK_CNODE_SUPER:
 | |
| 
 | |
| 			case HAK_CNODE_CLASS:
 | |
| 			case HAK_CNODE_FUN:
 | |
| 			case HAK_CNODE_DO:
 | |
| 			case HAK_CNODE_IF:
 | |
| 			case HAK_CNODE_ELIF:
 | |
| 			case HAK_CNODE_ELSE:
 | |
| 			case HAK_CNODE_THROW:
 | |
| 			case HAK_CNODE_TRY:
 | |
| 			case HAK_CNODE_CATCH:
 | |
| 			case HAK_CNODE_BREAK:
 | |
| 			case HAK_CNODE_CONTINUE:
 | |
| 			case HAK_CNODE_UNTIL:
 | |
| 			case HAK_CNODE_WHILE:
 | |
| 			case HAK_CNODE_RETURN:
 | |
| 			case HAK_CNODE_REVERT:
 | |
| 			case HAK_CNODE_AND:
 | |
| 			case HAK_CNODE_OR:
 | |
| #if defined(USE_KW_PLUS)
 | |
| 			case HAK_CNODE_PLUS:
 | |
| #endif
 | |
| 			case HAK_CNODE_SET:
 | |
| 			case HAK_CNODE_SET_R:
 | |
| 
 | |
| 			case HAK_CNODE_ELLIPSIS:
 | |
| 			case HAK_CNODE_TRPCOLONS:
 | |
| 			case HAK_CNODE_DBLCOLONS:
 | |
| 			case HAK_CNODE_COLON:
 | |
| 				hak_logbfmt(hak, HAK_LOG_FATAL, " %.*js ", HAK_CNODE_GET_TOKLEN(cnode), HAK_CNODE_GET_TOKPTR(cnode));
 | |
| 				break;
 | |
| 
 | |
| 			case HAK_CNODE_CONS:
 | |
| 			{
 | |
| 				hak_concode_t cc;
 | |
| 
 | |
| 				hak_logbfmt(hak, HAK_LOG_FATAL, " (");
 | |
| 				hak_dumpcnode(hak, HAK_CNODE_CONS_CAR(cnode), 0);
 | |
| 
 | |
| 				cc = HAK_CNODE_CONS_CONCODE(cnode);
 | |
| 				switch (cc)
 | |
| 				{
 | |
| 					case HAK_CONCODE_ALIST:
 | |
| 						hak_logbfmt(hak, HAK_LOG_FATAL, " := ");
 | |
| 						break;
 | |
| 					case HAK_CONCODE_BLIST:
 | |
| 					case HAK_CONCODE_MLIST:
 | |
| 						hak_logbfmt(hak, HAK_LOG_FATAL, ":");
 | |
| 						break;
 | |
| 				}
 | |
| 
 | |
| 				hak_dumpcnode(hak, HAK_CNODE_CONS_CDR(cnode),0);
 | |
| 				hak_logbfmt(hak, HAK_LOG_FATAL, ") ");
 | |
| 				break;
 | |
| 			}
 | |
| 
 | |
| 			case HAK_CNODE_ELIST:
 | |
| 				hak_logbfmt(hak, HAK_LOG_FATAL, " () ", HAK_CNODE_GET_TOKLEN(cnode), HAK_CNODE_GET_TOKPTR(cnode));
 | |
| 				break;
 | |
| 
 | |
| 			case HAK_CNODE_SHELL:
 | |
| 				hak_logbfmt(hak, HAK_LOG_FATAL, " () ", HAK_CNODE_GET_TOKLEN(cnode), HAK_CNODE_GET_TOKPTR(cnode));
 | |
| 				break;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (newline) hak_logbfmt(hak, HAK_LOG_FATAL, "\n");
 | |
| }
 | |
| 
 | |
| 
 |