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");
 | 
						|
}
 | 
						|
 | 
						|
 |