568 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			568 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
    Copyright (c) 2006-2020 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 "hawk-prv.h"
 | 
						|
 | 
						|
static int split_record (hawk_rtx_t* run, int prefer_number);
 | 
						|
static int recomp_record_fields (hawk_rtx_t* run, hawk_oow_t lv, const hawk_oocs_t* str, int prefer_number);
 | 
						|
 | 
						|
int hawk_rtx_setrec (hawk_rtx_t* rtx, hawk_oow_t idx, const hawk_oocs_t* str, int prefer_number)
 | 
						|
{
 | 
						|
	hawk_val_t* v;
 | 
						|
 | 
						|
	if (idx == 0)
 | 
						|
	{
 | 
						|
		if (str->ptr == HAWK_OOECS_PTR(&rtx->inrec.line) &&
 | 
						|
		    str->len == HAWK_OOECS_LEN(&rtx->inrec.line))
 | 
						|
		{
 | 
						|
			if (hawk_rtx_clrrec(rtx, 1) <= -1) return -1;
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			if (hawk_rtx_clrrec(rtx, 0) <= -1) return -1;
 | 
						|
			if (hawk_ooecs_ncpy(&rtx->inrec.line, str->ptr, str->len) == (hawk_oow_t)-1) goto oops;
 | 
						|
		}
 | 
						|
 | 
						|
		if (split_record(rtx, prefer_number) <= -1) goto oops;
 | 
						|
 | 
						|
		v = prefer_number? hawk_rtx_makenumorstrvalwithoochars(rtx, HAWK_OOECS_PTR(&rtx->inrec.line), HAWK_OOECS_LEN(&rtx->inrec.line)):  /* number or string */
 | 
						|
		                   hawk_rtx_makenstrvalwithoochars(rtx, HAWK_OOECS_PTR(&rtx->inrec.line), HAWK_OOECS_LEN(&rtx->inrec.line));  /* str with nstr flag */
 | 
						|
 | 
						|
		if (HAWK_UNLIKELY(!v)) goto oops;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		if (recomp_record_fields(rtx, idx, str, prefer_number) <= -1) goto oops;
 | 
						|
 | 
						|
		/* recompose $0 */
 | 
						|
		v = hawk_rtx_makestrvalwithoochars(rtx, HAWK_OOECS_PTR(&rtx->inrec.line), HAWK_OOECS_LEN(&rtx->inrec.line));
 | 
						|
		if (HAWK_UNLIKELY(!v)) goto oops;
 | 
						|
	}
 | 
						|
 | 
						|
	if (HAWK_RTX_GETVALTYPE(rtx, rtx->inrec.d0) != HAWK_VAL_NIL) hawk_rtx_refdownval (rtx, rtx->inrec.d0);
 | 
						|
	rtx->inrec.d0 = v;
 | 
						|
	hawk_rtx_refupval (rtx, v);
 | 
						|
 | 
						|
	return 0;
 | 
						|
 | 
						|
oops:
 | 
						|
	hawk_rtx_clrrec (rtx, 0);
 | 
						|
	return -1;
 | 
						|
}
 | 
						|
 | 
						|
#if 0
 | 
						|
static int merge_fields (hawk_rtx_t* rtx)
 | 
						|
{
 | 
						|
	hawk_oow_t i;
 | 
						|
 | 
						|
	hawk_ooecs_clear (&rtx->inrec.line);
 | 
						|
 | 
						|
	for (i = 0; i < rtx->inrec.nflds; i++)
 | 
						|
	{
 | 
						|
		hawk_ooch_t* vp;
 | 
						|
		hawk_oow_t vl;
 | 
						|
 | 
						|
		if (HAWK_LIKELY(i > 0))
 | 
						|
		{
 | 
						|
			if (hawk_ooecs_ncat(&rtx->inrec.line, rtx->gbl.ofs.ptr, rtx->gbl.ofs.len) == (hawk_oow_t)-1) return -1;
 | 
						|
		}
 | 
						|
 | 
						|
		vp = hawk_rtx_getvaloocstr(rtx, rtx->inrec.flds[i].val, &vl);
 | 
						|
		if (HAWK_UNLIKELY(!vp)) return -1;
 | 
						|
 | 
						|
		vl = hawk_ooecs_ncat(&rtx->inrec.line, vp, vl);
 | 
						|
		hawk_rtx_freevaloocstr (rtx, rtx->inrec.flds[i].val, vp);
 | 
						|
 | 
						|
		if (HAWK_UNLIKELY(vl == (hawk_oow_t)-1)) return -1;
 | 
						|
	}
 | 
						|
 | 
						|
	return 1;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
static int split_record (hawk_rtx_t* rtx, int prefer_number)
 | 
						|
{
 | 
						|
	hawk_oocs_t tok;
 | 
						|
	hawk_ooch_t* p, * px;
 | 
						|
	hawk_oow_t len, nflds;
 | 
						|
	hawk_val_t* v, * fs;
 | 
						|
	hawk_val_type_t fsvtype;
 | 
						|
	hawk_ooch_t* fs_ptr, * fs_free;
 | 
						|
	hawk_oow_t fs_len;
 | 
						|
	int how;
 | 
						|
 | 
						|
	/* inrec should be cleared before split_record is called */
 | 
						|
	HAWK_ASSERT(rtx->inrec.nflds == 0);
 | 
						|
 | 
						|
	/* get FS */
 | 
						|
	fs = hawk_rtx_getgbl(rtx, HAWK_GBL_FS);
 | 
						|
	fsvtype = HAWK_RTX_GETVALTYPE (rtx, fs);
 | 
						|
	if (fsvtype == HAWK_VAL_NIL)
 | 
						|
	{
 | 
						|
		fs_ptr = HAWK_T(" ");
 | 
						|
		fs_len = 1;
 | 
						|
		fs_free = HAWK_NULL;
 | 
						|
	}
 | 
						|
	else if (fsvtype == HAWK_VAL_STR)
 | 
						|
	{
 | 
						|
		fs_ptr = ((hawk_val_str_t*)fs)->val.ptr;
 | 
						|
		fs_len = ((hawk_val_str_t*)fs)->val.len;
 | 
						|
		fs_free = HAWK_NULL;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		fs_ptr = hawk_rtx_valtooocstrdup(rtx, fs, &fs_len);
 | 
						|
		if (HAWK_UNLIKELY(!fs_ptr)) return -1;
 | 
						|
		fs_free = fs_ptr;
 | 
						|
	}
 | 
						|
 | 
						|
	/* scan the input record to count the fields */
 | 
						|
	if (fs_len == 5 && fs_ptr[0] ==  HAWK_T('?'))
 | 
						|
	{
 | 
						|
		if (hawk_ooecs_ncpy(&rtx->inrec.linew, HAWK_OOECS_PTR(&rtx->inrec.line), HAWK_OOECS_LEN(&rtx->inrec.line)) == (hawk_oow_t)-1)
 | 
						|
		{
 | 
						|
			if (fs_free) hawk_rtx_freemem (rtx, fs_free);
 | 
						|
			return -1;
 | 
						|
		}
 | 
						|
 | 
						|
		px = HAWK_OOECS_PTR(&rtx->inrec.linew);
 | 
						|
		how = 1;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		px = HAWK_OOECS_PTR(&rtx->inrec.line);
 | 
						|
		how = (fs_len <= 1)? 0: 2;
 | 
						|
	}
 | 
						|
 | 
						|
	p = px;
 | 
						|
	len = HAWK_OOECS_LEN(&rtx->inrec.line);
 | 
						|
 | 
						|
#if 0
 | 
						|
	nflds = 0;
 | 
						|
	while (p != HAWK_NULL)
 | 
						|
	{
 | 
						|
		switch (how)
 | 
						|
		{
 | 
						|
			case 0:
 | 
						|
				p = hawk_rtx_tokoocharswithoochars (rtx, p, len, fs_ptr, fs_len, &tok);
 | 
						|
				break;
 | 
						|
 | 
						|
			case 1:
 | 
						|
				break;
 | 
						|
 | 
						|
			default:
 | 
						|
				p = hawk_rtx_tokoocharsbyrex(
 | 
						|
					rtx,
 | 
						|
					HAWK_OOECS_PTR(&rtx->inrec.line),
 | 
						|
					HAWK_OOECS_LEN(&rtx->inrec.line),
 | 
						|
					p, len,
 | 
						|
					rtx->gbl.fs[rtx->gbl.ignorecase], &tok
 | 
						|
				);
 | 
						|
				if (p == HAWK_NULL && hawk_rtx_geterrnum(rtx) != HAWK_ENOERR)
 | 
						|
				{
 | 
						|
					if (fs_free) hawk_rtx_freemem (rtx, fs_free);
 | 
						|
					return -1;
 | 
						|
				}
 | 
						|
		}
 | 
						|
 | 
						|
		if (nflds == 0 && p == HAWK_NULL && tok.len == 0)
 | 
						|
		{
 | 
						|
			/* there are no fields. it can just return here
 | 
						|
			 * as hawk_rtx_clrrec has been called before this */
 | 
						|
			if (fs_free) hawk_rtx_freemem (rtx, fs_free);
 | 
						|
			return 0;
 | 
						|
		}
 | 
						|
 | 
						|
		HAWK_ASSERT((tok.ptr != HAWK_NULL && tok.len > 0) || tok.len == 0);
 | 
						|
 | 
						|
		nflds++;
 | 
						|
		len = HAWK_OOECS_LEN(&rtx->inrec.line) - (p - HAWK_OOECS_PTR(&rtx->inrec.line));
 | 
						|
	}
 | 
						|
 | 
						|
	/* allocate space */
 | 
						|
	if (nflds > rtx->inrec.maxflds)
 | 
						|
	{
 | 
						|
		void* tmp = hawk_rtx_allocmem(rtx, HAWK_SIZEOF(*rtx->inrec.flds) * nflds);
 | 
						|
		if (HAWK_UNLIKELY(!tmp))
 | 
						|
		{
 | 
						|
			if (fs_free) hawk_rtx_freemem (rtx, fs_free);
 | 
						|
			return -1;
 | 
						|
		}
 | 
						|
 | 
						|
		if (rtx->inrec.flds) hawk_rtx_freemem (rtx, rtx->inrec.flds);
 | 
						|
		rtx->inrec.flds = tmp;
 | 
						|
		rtx->inrec.maxflds = nflds;
 | 
						|
	}
 | 
						|
 | 
						|
	/* scan again and split it */
 | 
						|
	if (how == 1)
 | 
						|
	{
 | 
						|
		if (hawk_ooecs_ncpy(&rtx->inrec.linew, HAWK_OOECS_PTR(&rtx->inrec.line), HAWK_OOECS_LEN(&rtx->inrec.line)) == (hawk_oow_t)-1)
 | 
						|
		{
 | 
						|
			if (fs_free) hawk_rtx_freemem (rtx, fs_free);
 | 
						|
			return -1;
 | 
						|
		}
 | 
						|
		px = HAWK_OOECS_PTR(&rtx->inrec.linew):
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		px = HAWK_OOECS_PTR(&rtx->inrec.line);
 | 
						|
	}
 | 
						|
 | 
						|
	p = px;
 | 
						|
	len = HAWK_OOECS_LEN(&rtx->inrec.line);
 | 
						|
#endif
 | 
						|
 | 
						|
	while (p)
 | 
						|
	{
 | 
						|
		switch (how)
 | 
						|
		{
 | 
						|
			case 0:
 | 
						|
				/* 1 character FS */
 | 
						|
				p = hawk_rtx_tokoocharswithoochars(rtx, p, len, fs_ptr, fs_len, &tok);
 | 
						|
				break;
 | 
						|
 | 
						|
			case 1:
 | 
						|
				/* 5 character FS beginning with ? */
 | 
						|
				p = hawk_rtx_fldoochars(rtx, p, len, fs_ptr[1], fs_ptr[2], fs_ptr[3], fs_ptr[4], &tok);
 | 
						|
				break;
 | 
						|
 | 
						|
			default:
 | 
						|
				/* all other cases */
 | 
						|
				p = hawk_rtx_tokoocharsbyrex(
 | 
						|
					rtx,
 | 
						|
					HAWK_OOECS_PTR(&rtx->inrec.line),
 | 
						|
					HAWK_OOECS_LEN(&rtx->inrec.line),
 | 
						|
					p, len,
 | 
						|
					rtx->gbl.fs[rtx->gbl.ignorecase], &tok
 | 
						|
				);
 | 
						|
				if (p == HAWK_NULL && hawk_rtx_geterrnum(rtx) != HAWK_ENOERR)
 | 
						|
				{
 | 
						|
					if (fs_free) hawk_rtx_freemem (rtx, fs_free);
 | 
						|
					return -1;
 | 
						|
				}
 | 
						|
		}
 | 
						|
#if 1
 | 
						|
		if (rtx->inrec.nflds == 0 && p == HAWK_NULL && tok.len == 0)
 | 
						|
		{
 | 
						|
			/* there are no fields. it can just return here
 | 
						|
			 * as hawk_rtx_clrrec has been called before this */
 | 
						|
			if (fs_free) hawk_rtx_freemem (rtx, fs_free);
 | 
						|
			return 0;
 | 
						|
		}
 | 
						|
#endif
 | 
						|
 | 
						|
		HAWK_ASSERT((tok.ptr != HAWK_NULL && tok.len > 0) || tok.len == 0);
 | 
						|
 | 
						|
#if 1
 | 
						|
		if (rtx->inrec.nflds >= rtx->inrec.maxflds)
 | 
						|
		{
 | 
						|
			void* tmp;
 | 
						|
 | 
						|
			if (rtx->inrec.nflds < 16) nflds = 32;
 | 
						|
			else nflds = rtx->inrec.nflds * 2;
 | 
						|
 | 
						|
			tmp = hawk_rtx_allocmem(rtx, HAWK_SIZEOF(*rtx->inrec.flds) * nflds);
 | 
						|
			if (tmp == HAWK_NULL)
 | 
						|
			{
 | 
						|
				if (fs_free) hawk_rtx_freemem (rtx, fs_free);
 | 
						|
				return -1;
 | 
						|
			}
 | 
						|
 | 
						|
			if (rtx->inrec.flds != HAWK_NULL)
 | 
						|
			{
 | 
						|
				HAWK_MEMCPY (tmp, rtx->inrec.flds, HAWK_SIZEOF(*rtx->inrec.flds) * rtx->inrec.nflds);
 | 
						|
				hawk_rtx_freemem (rtx, rtx->inrec.flds);
 | 
						|
			}
 | 
						|
 | 
						|
			rtx->inrec.flds = tmp;
 | 
						|
			rtx->inrec.maxflds = nflds;
 | 
						|
		}
 | 
						|
#endif
 | 
						|
 | 
						|
		rtx->inrec.flds[rtx->inrec.nflds].ptr = tok.ptr;
 | 
						|
		rtx->inrec.flds[rtx->inrec.nflds].len = tok.len;
 | 
						|
		/*rtx->inrec.flds[rtx->inrec.nflds].val = hawk_rtx_makenstrvalwithoocs(rtx, &tok);*/
 | 
						|
		rtx->inrec.flds[rtx->inrec.nflds].val =
 | 
						|
			prefer_number? hawk_rtx_makenumorstrvalwithoochars(rtx, tok.ptr, tok.len):
 | 
						|
			               hawk_rtx_makestrvalwithoochars(rtx, tok.ptr, tok.len);
 | 
						|
		if (HAWK_UNLIKELY(!rtx->inrec.flds[rtx->inrec.nflds].val))
 | 
						|
		{
 | 
						|
			if (fs_free) hawk_rtx_freemem (rtx, fs_free);
 | 
						|
			return -1;
 | 
						|
		}
 | 
						|
 | 
						|
		hawk_rtx_refupval (rtx, rtx->inrec.flds[rtx->inrec.nflds].val);
 | 
						|
		rtx->inrec.nflds++;
 | 
						|
 | 
						|
		len = HAWK_OOECS_LEN(&rtx->inrec.line) - (p - px);
 | 
						|
	}
 | 
						|
 | 
						|
	if (fs_free) hawk_rtx_freemem (rtx, fs_free);
 | 
						|
 | 
						|
	/* set the number of fields */
 | 
						|
	v = hawk_rtx_makeintval(rtx, (hawk_int_t)rtx->inrec.nflds);
 | 
						|
	if (v == HAWK_NULL) return -1;
 | 
						|
 | 
						|
	hawk_rtx_refupval (rtx, v);
 | 
						|
	if (hawk_rtx_setgbl(rtx, HAWK_GBL_NF, v) <= -1)
 | 
						|
	{
 | 
						|
		hawk_rtx_refdownval (rtx, v);
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
	hawk_rtx_refdownval (rtx, v);
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
int hawk_rtx_clrrec (hawk_rtx_t* rtx, int skip_inrec_line)
 | 
						|
{
 | 
						|
	hawk_oow_t i;
 | 
						|
	int n = 0;
 | 
						|
 | 
						|
	if (HAWK_RTX_GETVALTYPE(rtx, rtx->inrec.d0) != HAWK_VAL_NIL)
 | 
						|
	{
 | 
						|
		hawk_rtx_refdownval (rtx, rtx->inrec.d0);
 | 
						|
		rtx->inrec.d0 = hawk_val_nil;
 | 
						|
	}
 | 
						|
 | 
						|
	if (rtx->inrec.nflds > 0)
 | 
						|
	{
 | 
						|
		HAWK_ASSERT(rtx->inrec.flds != HAWK_NULL);
 | 
						|
 | 
						|
		for (i = 0; i < rtx->inrec.nflds; i++)
 | 
						|
		{
 | 
						|
			HAWK_ASSERT(rtx->inrec.flds[i].val != HAWK_NULL);
 | 
						|
			hawk_rtx_refdownval (rtx, rtx->inrec.flds[i].val);
 | 
						|
		}
 | 
						|
		rtx->inrec.nflds = 0;
 | 
						|
 | 
						|
		if (hawk_rtx_setgbl(rtx, HAWK_GBL_NF, HAWK_VAL_ZERO) <= -1)
 | 
						|
		{
 | 
						|
			/* first of all, this should never happen.
 | 
						|
			 * if it happened, it would return an error
 | 
						|
			 * after all the clearance tasks */
 | 
						|
			n = -1;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	HAWK_ASSERT(rtx->inrec.nflds == 0);
 | 
						|
	if (!skip_inrec_line) hawk_ooecs_clear (&rtx->inrec.line);
 | 
						|
 | 
						|
	return n;
 | 
						|
}
 | 
						|
 | 
						|
static int recomp_record_fields (hawk_rtx_t* rtx, hawk_oow_t lv, const hawk_oocs_t* str, int prefer_number)
 | 
						|
{
 | 
						|
	hawk_val_t* v;
 | 
						|
	hawk_oow_t max, i, nflds;
 | 
						|
 | 
						|
	/* recomposes the record and the fields when $N has been assigned
 | 
						|
	 * a new value and recomputes NF accordingly.
 | 
						|
	 *
 | 
						|
	 * BEGIN { OFS=":" } { $2 = "Q"; print $0; }
 | 
						|
	 * If input is abc def xxx, $0 becomes abc:Q:xxx.
 | 
						|
	 *
 | 
						|
	 * We should store the value in rtx->inrec.line so that the caller
 | 
						|
	 * can use it to make a value for $0.
 | 
						|
	 */
 | 
						|
 | 
						|
	HAWK_ASSERT(lv > 0);
 | 
						|
	max = (lv > rtx->inrec.nflds)? lv: rtx->inrec.nflds;
 | 
						|
 | 
						|
	nflds = rtx->inrec.nflds;
 | 
						|
	if (max > rtx->inrec.maxflds)
 | 
						|
	{
 | 
						|
		void* tmp;
 | 
						|
 | 
						|
		/* if the given field number is greater than the maximum
 | 
						|
		 * number of fields that the current record can hold,
 | 
						|
		 * the field spaces are resized */
 | 
						|
 | 
						|
		tmp = hawk_rtx_reallocmem(rtx, rtx->inrec.flds, HAWK_SIZEOF(*rtx->inrec.flds) * max);
 | 
						|
		if (HAWK_UNLIKELY(!tmp)) return -1;
 | 
						|
 | 
						|
		rtx->inrec.flds = tmp;
 | 
						|
		rtx->inrec.maxflds = max;
 | 
						|
	}
 | 
						|
 | 
						|
	lv = lv - 1; /* adjust the value to 0-based index */
 | 
						|
 | 
						|
	hawk_ooecs_clear (&rtx->inrec.line);
 | 
						|
 | 
						|
	for (i = 0; i < max; i++)
 | 
						|
	{
 | 
						|
		if (i > 0)
 | 
						|
		{
 | 
						|
			if (hawk_ooecs_ncat(&rtx->inrec.line, rtx->gbl.ofs.ptr, rtx->gbl.ofs.len) == (hawk_oow_t)-1) return -1;
 | 
						|
		}
 | 
						|
 | 
						|
		if (i == lv)
 | 
						|
		{
 | 
						|
			hawk_val_t* tmp;
 | 
						|
 | 
						|
			rtx->inrec.flds[i].ptr = HAWK_OOECS_PTR(&rtx->inrec.line) + HAWK_OOECS_LEN(&rtx->inrec.line);
 | 
						|
			rtx->inrec.flds[i].len = str->len;
 | 
						|
 | 
						|
			if (hawk_ooecs_ncat(&rtx->inrec.line, str->ptr, str->len) == (hawk_oow_t)-1) return -1;
 | 
						|
 | 
						|
			tmp = prefer_number? hawk_rtx_makenumorstrvalwithoochars(rtx, str->ptr, str->len):
 | 
						|
			                     hawk_rtx_makestrvalwithoochars(rtx, str->ptr, str->len);
 | 
						|
			if (HAWK_UNLIKELY(!tmp)) return -1;
 | 
						|
 | 
						|
			if (i < nflds) hawk_rtx_refdownval (rtx, rtx->inrec.flds[i].val);
 | 
						|
			else rtx->inrec.nflds++;
 | 
						|
 | 
						|
			rtx->inrec.flds[i].val = tmp;
 | 
						|
			hawk_rtx_refupval (rtx, tmp);
 | 
						|
		}
 | 
						|
		else if (i >= nflds)
 | 
						|
		{
 | 
						|
			rtx->inrec.flds[i].ptr = HAWK_OOECS_PTR(&rtx->inrec.line) + HAWK_OOECS_LEN(&rtx->inrec.line);
 | 
						|
			rtx->inrec.flds[i].len = 0;
 | 
						|
 | 
						|
			if (hawk_ooecs_cat(&rtx->inrec.line, HAWK_T("")) == (hawk_oow_t)-1) return -1;
 | 
						|
 | 
						|
			/* hawk_rtx_refdownval should not be called over
 | 
						|
			 * rtx->inrec.flds[i].val as it is not initialized
 | 
						|
			 * to any valid values */
 | 
						|
			/*hawk_rtx_refdownval (rtx, rtx->inrec.flds[i].val);*/
 | 
						|
			rtx->inrec.flds[i].val = hawk_val_zls;
 | 
						|
			hawk_rtx_refupval (rtx, hawk_val_zls);
 | 
						|
			rtx->inrec.nflds++;
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			hawk_ooch_t* vp;
 | 
						|
			hawk_oow_t vl;
 | 
						|
 | 
						|
			vp = hawk_rtx_getvaloocstr(rtx, rtx->inrec.flds[i].val, &vl);
 | 
						|
			if (HAWK_UNLIKELY(!vp)) return -1;
 | 
						|
 | 
						|
			vl = hawk_ooecs_ncat(&rtx->inrec.line, vp, vl);
 | 
						|
			hawk_rtx_freevaloocstr (rtx, rtx->inrec.flds[i].val, vp);
 | 
						|
 | 
						|
			if (HAWK_UNLIKELY(vl == (hawk_oow_t)-1)) return -1;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	v = hawk_rtx_getgbl(rtx, HAWK_GBL_NF);
 | 
						|
	HAWK_ASSERT(HAWK_RTX_GETVALTYPE(rtx, v) == HAWK_VAL_INT);
 | 
						|
 | 
						|
	if (HAWK_RTX_GETINTFROMVAL(rtx, v) != max)
 | 
						|
	{
 | 
						|
		v = hawk_rtx_makeintval (rtx, (hawk_int_t)max);
 | 
						|
		if (v == HAWK_NULL) return -1;
 | 
						|
 | 
						|
		hawk_rtx_refupval (rtx, v);
 | 
						|
		if (hawk_rtx_setgbl(rtx, HAWK_GBL_NF, v) <= -1)
 | 
						|
		{
 | 
						|
			hawk_rtx_refdownval (rtx, v);
 | 
						|
			return -1;
 | 
						|
		}
 | 
						|
		hawk_rtx_refdownval (rtx, v);
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
int hawk_rtx_truncrec (hawk_rtx_t* rtx, hawk_oow_t nflds)
 | 
						|
{
 | 
						|
	hawk_val_t* v = HAWK_NULL, * w;
 | 
						|
	hawk_ooch_t* ofs_free = HAWK_NULL, * ofs_ptr;
 | 
						|
	hawk_oow_t ofs_len, i;
 | 
						|
	hawk_val_type_t vtype;
 | 
						|
	hawk_ooecs_t tmp;
 | 
						|
	int fini_tmp = 0;
 | 
						|
 | 
						|
	HAWK_ASSERT(nflds <= rtx->inrec.nflds);
 | 
						|
 | 
						|
	if (hawk_ooecs_init(&tmp, hawk_rtx_getgem(rtx), HAWK_OOECS_LEN(&rtx->inrec.line)) <= -1) goto oops;
 | 
						|
	fini_tmp = 1;
 | 
						|
 | 
						|
	if (nflds > 0)
 | 
						|
	{
 | 
						|
		if (nflds > 1)
 | 
						|
		{
 | 
						|
			v = HAWK_RTX_STACK_GBL(rtx, HAWK_GBL_OFS);
 | 
						|
			hawk_rtx_refupval (rtx, v);
 | 
						|
			vtype = HAWK_RTX_GETVALTYPE(rtx, v);
 | 
						|
 | 
						|
			if (vtype == HAWK_VAL_NIL)
 | 
						|
			{
 | 
						|
				/* OFS not set */
 | 
						|
				ofs_ptr = HAWK_T(" ");
 | 
						|
				ofs_len = 1;
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
				ofs_ptr = hawk_rtx_getvaloocstr(rtx, v, &ofs_len);
 | 
						|
				if (HAWK_UNLIKELY(!ofs_ptr)) goto oops;
 | 
						|
				ofs_free = ofs_ptr;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		if (hawk_ooecs_ncat(&tmp, rtx->inrec.flds[0].ptr, rtx->inrec.flds[0].len) == (hawk_oow_t)-1) goto oops;
 | 
						|
		for (i = 1; i < nflds; i++)
 | 
						|
		{
 | 
						|
			if (i > 0 && hawk_ooecs_ncat(&tmp,ofs_ptr,ofs_len) == (hawk_oow_t)-1) goto oops;
 | 
						|
			if (hawk_ooecs_ncat(&tmp, rtx->inrec.flds[i].ptr, rtx->inrec.flds[i].len) == (hawk_oow_t)-1) goto oops;
 | 
						|
		}
 | 
						|
 | 
						|
		if (v)
 | 
						|
		{
 | 
						|
			if (ofs_free) hawk_rtx_freevaloocstr (rtx, v, ofs_free);
 | 
						|
			hawk_rtx_refdownval(rtx, v);
 | 
						|
			v = HAWK_NULL;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	w = (hawk_val_t*)hawk_rtx_makestrvalwithoocs(rtx, HAWK_OOECS_OOCS(&tmp));
 | 
						|
	if (HAWK_UNLIKELY(!w)) goto oops;
 | 
						|
 | 
						|
	hawk_rtx_refdownval (rtx, rtx->inrec.d0);
 | 
						|
	rtx->inrec.d0 = w;
 | 
						|
	hawk_rtx_refupval (rtx, rtx->inrec.d0);
 | 
						|
 | 
						|
	hawk_ooecs_swap (&tmp, &rtx->inrec.line);
 | 
						|
	hawk_ooecs_fini (&tmp);
 | 
						|
	fini_tmp = 0;
 | 
						|
 | 
						|
	for (i = nflds; i < rtx->inrec.nflds; i++)
 | 
						|
	{
 | 
						|
		hawk_rtx_refdownval (rtx, rtx->inrec.flds[i].val);
 | 
						|
	}
 | 
						|
 | 
						|
	rtx->inrec.nflds = nflds;
 | 
						|
	return 0;
 | 
						|
 | 
						|
oops:
 | 
						|
	if (fini_tmp) hawk_ooecs_fini (&tmp);
 | 
						|
	if (v)
 | 
						|
	{
 | 
						|
		if (ofs_free) hawk_rtx_freevaloocstr (rtx, v, ofs_free);
 | 
						|
		hawk_rtx_refdownval(rtx, v);
 | 
						|
	}
 | 
						|
	return -1;
 | 
						|
}
 |