added qse_awk_rtx_getrefvaltype()/qse_awk_rtx_getrefval()
finished asort() in awk added qse_sortx()
This commit is contained in:
		@ -2958,6 +2958,21 @@ QSE_EXPORT qse_awk_int_t qse_awk_rtx_hashval (
 | 
			
		||||
	qse_awk_val_t* v
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The qse_awk_rtx_getrefvaltype() function returns the type of the value
 | 
			
		||||
 * that the given reference points to.
 | 
			
		||||
 */
 | 
			
		||||
QSE_EXPORT qse_awk_val_type_t qse_awk_rtx_getrefvaltype (
 | 
			
		||||
	qse_awk_rtx_t*     rtx,
 | 
			
		||||
	qse_awk_val_ref_t* ref
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_getrefval (
 | 
			
		||||
	qse_awk_rtx_t*     rtx,
 | 
			
		||||
	qse_awk_val_ref_t* ref
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The qse_awk_rtx_setrefval() function changes the value
 | 
			
		||||
 * of a variable referenced in \a ref. 
 | 
			
		||||
 | 
			
		||||
@ -55,10 +55,23 @@ typedef int (*qse_search_comper_t) (
 | 
			
		||||
	void*       ctx
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The qse_search_comperx_t type defines a search callback function.
 | 
			
		||||
 * It should return 0 on success and -1 on failure. the comparsion
 | 
			
		||||
 * result must be put back into the variable pointed to by \a cv.
 | 
			
		||||
 */
 | 
			
		||||
typedef int (*qse_search_comperx_t) (
 | 
			
		||||
	const void* ptr1, 
 | 
			
		||||
	const void* ptr2, 
 | 
			
		||||
	void*       ctx,
 | 
			
		||||
	int *       cv
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The qse_sort_comper_t type defines a sort callback function.
 | 
			
		||||
 */
 | 
			
		||||
typedef qse_search_comper_t qse_sort_comper_t;
 | 
			
		||||
typedef qse_search_comperx_t qse_sort_comperx_t;
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
extern "C" {
 | 
			
		||||
@ -134,6 +147,14 @@ QSE_EXPORT void qse_qsort (
 | 
			
		||||
	void*             ctx
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
QSE_EXPORT int qse_qsortx (
 | 
			
		||||
	void*              base,
 | 
			
		||||
	qse_size_t         nmemb,
 | 
			
		||||
	qse_size_t         size,
 | 
			
		||||
	qse_sort_comperx_t comper,
 | 
			
		||||
	void*              ctx
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The qse_rand31() function implements Park-Miller's minimal standard
 | 
			
		||||
 | 
			
		||||
@ -45,7 +45,7 @@ static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi);
 | 
			
		||||
 *
 | 
			
		||||
 * - v: value. pass it after normal evaluation.
 | 
			
		||||
 * - r: pass a variable by reference
 | 
			
		||||
 * - x: regular expression as it it. not evaluated as /rex/ ~ $0.
 | 
			
		||||
 * - x: regular expression as it is. not evaluated as /rex/ ~ $0.
 | 
			
		||||
 *
 | 
			
		||||
 * If the first character of the specifer is 'R', all
 | 
			
		||||
 * parameters are passed by reference regarless of the remaining
 | 
			
		||||
@ -67,30 +67,30 @@ static qse_awk_fnc_t sysfnctab[] =
 | 
			
		||||
	{ {QSE_T("typename"), 8}, 0, { {1,     1, QSE_NULL},       fnc_typename,         0 }, QSE_NULL},
 | 
			
		||||
 | 
			
		||||
	/* array sort */
 | 
			
		||||
	{ {QSE_T("asort"),    5}, 0, { {1,     3, QSE_NULL},       fnc_asort,            0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("asort"),    5}, 0, { {1,     3, QSE_T("rrv")},   fnc_asort,            0 }, QSE_NULL},
 | 
			
		||||
 
 | 
			
		||||
	/* string functions */
 | 
			
		||||
	{ {QSE_T("gsub"),     4}, 0, { {2,     3, QSE_T("xvr")},  qse_awk_fnc_gsub,     0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("index"),    5}, 0, { {2,     3, QSE_NULL},      qse_awk_fnc_index,    0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("length"),   6}, 1, { {0,     1, QSE_NULL},      qse_awk_fnc_length,   0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("match"),    5}, 0, { {2,     4, QSE_T("vxvr")}, qse_awk_fnc_match,    0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("split"),    5}, 0, { {2,     3, QSE_T("vrx")},  qse_awk_fnc_split,    0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("sprintf"),  7}, 0, { {1, A_MAX, QSE_NULL},      qse_awk_fnc_sprintf,  0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("sub"),      3}, 0, { {2,     3, QSE_T("xvr")},  qse_awk_fnc_sub,      0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("substr"),   6}, 0, { {2,     3, QSE_NULL},      qse_awk_fnc_substr,   0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("tolower"),  7}, 0, { {1,     1, QSE_NULL},      qse_awk_fnc_tolower,  0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("toupper"),  7}, 0, { {1,     1, QSE_NULL},      qse_awk_fnc_toupper,  0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("gsub"),     4}, 0, { {2,     3, QSE_T("xvr")},   qse_awk_fnc_gsub,     0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("index"),    5}, 0, { {2,     3, QSE_NULL},       qse_awk_fnc_index,    0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("length"),   6}, 1, { {0,     1, QSE_NULL},       qse_awk_fnc_length,   0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("match"),    5}, 0, { {2,     4, QSE_T("vxvr")},  qse_awk_fnc_match,    0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("split"),    5}, 0, { {2,     3, QSE_T("vrx")},   qse_awk_fnc_split,    0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("sprintf"),  7}, 0, { {1, A_MAX, QSE_NULL},       qse_awk_fnc_sprintf,  0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("sub"),      3}, 0, { {2,     3, QSE_T("xvr")},   qse_awk_fnc_sub,      0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("substr"),   6}, 0, { {2,     3, QSE_NULL},       qse_awk_fnc_substr,   0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("tolower"),  7}, 0, { {1,     1, QSE_NULL},       qse_awk_fnc_tolower,  0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("toupper"),  7}, 0, { {1,     1, QSE_NULL},       qse_awk_fnc_toupper,  0 }, QSE_NULL},
 | 
			
		||||
 | 
			
		||||
	/* math functions */
 | 
			
		||||
	{ {QSE_T("sin"),      3}, 0, { {A_MAX, 0, QSE_T("math") },   QSE_NULL,         0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("cos"),      3}, 0, { {A_MAX, 0, QSE_T("math") },   QSE_NULL,         0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("tan"),      3}, 0, { {A_MAX, 0, QSE_T("math") },   QSE_NULL,         0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("atan"),     4}, 0, { {A_MAX, 0, QSE_T("math") },   QSE_NULL,         0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("atan2"),    5}, 0, { {A_MAX, 0, QSE_T("math") },   QSE_NULL,         0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("log"),      3}, 0, { {A_MAX, 0, QSE_T("math") },   QSE_NULL,         0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("log10"),    5}, 0, { {A_MAX, 0, QSE_T("math") },   QSE_NULL,         0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("exp"),      3}, 0, { {A_MAX, 0, QSE_T("math") },   QSE_NULL,         0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("sqrt"),     4}, 0, { {A_MAX, 0, QSE_T("math") },   QSE_NULL,         0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("sin"),      3}, 0, { {A_MAX, 0, QSE_T("math") },  QSE_NULL,         0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("cos"),      3}, 0, { {A_MAX, 0, QSE_T("math") },  QSE_NULL,         0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("tan"),      3}, 0, { {A_MAX, 0, QSE_T("math") },  QSE_NULL,         0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("atan"),     4}, 0, { {A_MAX, 0, QSE_T("math") },  QSE_NULL,         0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("atan2"),    5}, 0, { {A_MAX, 0, QSE_T("math") },  QSE_NULL,         0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("log"),      3}, 0, { {A_MAX, 0, QSE_T("math") },  QSE_NULL,         0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("log10"),    5}, 0, { {A_MAX, 0, QSE_T("math") },  QSE_NULL,         0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("exp"),      3}, 0, { {A_MAX, 0, QSE_T("math") },  QSE_NULL,         0 }, QSE_NULL},
 | 
			
		||||
	{ {QSE_T("sqrt"),     4}, 0, { {A_MAX, 0, QSE_T("math") },  QSE_NULL,         0 }, QSE_NULL},
 | 
			
		||||
 | 
			
		||||
	/* time functions */
 | 
			
		||||
	{ {QSE_T("mktime"),   6}, 0, { {A_MAX, 0, QSE_T("sys") },   QSE_NULL,          0 }, QSE_NULL},
 | 
			
		||||
@ -704,7 +704,6 @@ int qse_awk_fnc_split (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
 | 
			
		||||
	a2 = (nargs >= 3)? qse_awk_rtx_getarg (rtx, 2): QSE_NULL;
 | 
			
		||||
 | 
			
		||||
	a1_vtype = QSE_AWK_RTX_GETVALTYPE (rtx, a1);
 | 
			
		||||
 | 
			
		||||
	QSE_ASSERT (a1_vtype == QSE_AWK_VAL_REF);
 | 
			
		||||
 | 
			
		||||
	str.ptr = qse_awk_rtx_getvalstr(rtx, a0, &str.len);
 | 
			
		||||
@ -714,7 +713,7 @@ int qse_awk_fnc_split (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
 | 
			
		||||
	{
 | 
			
		||||
		/* get the value from FS */
 | 
			
		||||
		t1 = qse_awk_rtx_getgbl(rtx, QSE_AWK_GBL_FS);
 | 
			
		||||
		t1_vtype = QSE_AWK_RTX_GETVALTYPE (rtx, t1);
 | 
			
		||||
		t1_vtype = QSE_AWK_RTX_GETVALTYPE(rtx, t1);
 | 
			
		||||
		if (t1_vtype == QSE_AWK_VAL_NIL)
 | 
			
		||||
		{
 | 
			
		||||
			fs.ptr = QSE_T(" ");
 | 
			
		||||
@ -727,7 +726,7 @@ int qse_awk_fnc_split (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			fs.ptr = qse_awk_rtx_valtostrdup (rtx, t1, &fs.len);
 | 
			
		||||
			fs.ptr = qse_awk_rtx_valtostrdup(rtx, t1, &fs.len);
 | 
			
		||||
			if (fs.ptr == QSE_NULL) goto oops;
 | 
			
		||||
			fs_free = (qse_char_t*)fs.ptr;
 | 
			
		||||
		}
 | 
			
		||||
@ -801,15 +800,11 @@ int qse_awk_fnc_split (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
 | 
			
		||||
 | 
			
		||||
		if (fs.len <= 1)
 | 
			
		||||
		{
 | 
			
		||||
			p = qse_awk_rtx_strxntok (rtx, 
 | 
			
		||||
				p, str.len, fs.ptr, fs.len, &tok);
 | 
			
		||||
			p = qse_awk_rtx_strxntok(rtx, p, str.len, fs.ptr, fs.len, &tok);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			p = qse_awk_rtx_strxntokbyrex (
 | 
			
		||||
				rtx, str.ptr, org_len, p, str.len, 
 | 
			
		||||
				fs_rex, &tok, &errnum
 | 
			
		||||
			); 
 | 
			
		||||
			p = qse_awk_rtx_strxntokbyrex(rtx, str.ptr, org_len, p, str.len, fs_rex, &tok, &errnum); 
 | 
			
		||||
			if (p == QSE_NULL && errnum != QSE_AWK_ENOERR)
 | 
			
		||||
			{
 | 
			
		||||
				qse_awk_rtx_seterrnum (rtx, errnum, QSE_NULL);
 | 
			
		||||
@ -821,7 +816,7 @@ int qse_awk_fnc_split (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
 | 
			
		||||
		{
 | 
			
		||||
			/* no field at all*/
 | 
			
		||||
			break; 
 | 
			
		||||
		}	
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		QSE_ASSERT ((tok.ptr != QSE_NULL && tok.len > 0) || tok.len == 0);
 | 
			
		||||
 | 
			
		||||
@ -848,13 +843,13 @@ int qse_awk_fnc_split (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
 | 
			
		||||
	/*if (str_free) QSE_AWK_FREE (rtx->awk, str_free);*/
 | 
			
		||||
	qse_awk_rtx_freevalstr (rtx, a0, str.ptr);
 | 
			
		||||
 | 
			
		||||
	if (fs_free) QSE_AWK_FREE (rtx->awk, fs_free);
 | 
			
		||||
	if (fs_free) qse_awk_rtx_freemem (rtx, fs_free);
 | 
			
		||||
 | 
			
		||||
	if (fs_rex_free) 
 | 
			
		||||
	{
 | 
			
		||||
		if (rtx->gbl.ignorecase)
 | 
			
		||||
			qse_awk_freerex (rtx->awk, QSE_NULL, fs_rex_free);
 | 
			
		||||
		else	
 | 
			
		||||
		else
 | 
			
		||||
			qse_awk_freerex (rtx->awk, fs_rex_free, QSE_NULL);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -870,13 +865,13 @@ oops:
 | 
			
		||||
	/*if (str_free) QSE_AWK_FREE (rtx->awk, str_free);*/
 | 
			
		||||
	if (str.ptr) qse_awk_rtx_freevalstr (rtx, a0, str.ptr);
 | 
			
		||||
 | 
			
		||||
	if (fs_free) QSE_AWK_FREE (rtx->awk, fs_free);
 | 
			
		||||
	if (fs_free) qse_awk_rtx_freemem (rtx, fs_free);
 | 
			
		||||
 | 
			
		||||
	if (fs_rex_free) 
 | 
			
		||||
	{
 | 
			
		||||
		if (rtx->gbl.ignorecase)
 | 
			
		||||
			qse_awk_freerex (rtx->awk, QSE_NULL, fs_rex_free);
 | 
			
		||||
		else	
 | 
			
		||||
		else
 | 
			
		||||
			qse_awk_freerex (rtx->awk, fs_rex_free, QSE_NULL);
 | 
			
		||||
	}
 | 
			
		||||
	return -1;
 | 
			
		||||
@ -1531,31 +1526,58 @@ static int fnc_ismap (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static QSE_INLINE int asort_compare (const void* x1, const void* x2, void* ctx)
 | 
			
		||||
static QSE_INLINE int asort_compare (const void* x1, const void* x2, void* ctx, int* cv)
 | 
			
		||||
{
 | 
			
		||||
	int n;
 | 
			
		||||
	if (qse_awk_rtx_cmpval((qse_awk_rtx_t*)ctx, (qse_awk_val_t*)x1, (qse_awk_val_t*)x2, &n) <= -1) return -1;
 | 
			
		||||
	return n;
 | 
			
		||||
	if (qse_awk_rtx_cmpval((qse_awk_rtx_t*)ctx, *(qse_awk_val_t**)x1, *(qse_awk_val_t**)x2, &n) <= -1) return -1;
 | 
			
		||||
	*cv = n;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct cud_t
 | 
			
		||||
{
 | 
			
		||||
	qse_awk_rtx_t* rtx;
 | 
			
		||||
	qse_awk_fun_t* fun;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static QSE_INLINE int asort_compare_ud (const void* x1, const void* x2, void* ctx, int* cv)
 | 
			
		||||
{
 | 
			
		||||
	struct cud_t* cud = (struct cud_t*)ctx;
 | 
			
		||||
	qse_awk_val_t* r, * args[2];
 | 
			
		||||
	qse_awk_int_t rv;
 | 
			
		||||
 | 
			
		||||
	args[0] = *(qse_awk_val_t**)x1;
 | 
			
		||||
	args[1] = *(qse_awk_val_t**)x2;
 | 
			
		||||
	r = qse_awk_rtx_callfun(cud->rtx, cud->fun, args, 2); 
 | 
			
		||||
	if (!r) return -1;
 | 
			
		||||
	if (qse_awk_rtx_valtoint(cud->rtx, r,  &rv) <= -1) return -1;
 | 
			
		||||
	*cv = rv;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
 | 
			
		||||
{
 | 
			
		||||
	qse_size_t nargs;
 | 
			
		||||
	qse_awk_val_t* a0, * a2;
 | 
			
		||||
	qse_awk_val_t* a0, * a0_val, * a1, * a2;
 | 
			
		||||
	qse_awk_val_type_t a0_type, v_type;
 | 
			
		||||
	qse_awk_val_t* r, * rmap;
 | 
			
		||||
	qse_awk_int_t rv = 0; /* as if no element in the map */
 | 
			
		||||
	qse_awk_val_map_itr_t itr;
 | 
			
		||||
	qse_awk_fun_t* fun;
 | 
			
		||||
	qse_awk_fun_t* fun = QSE_NULL;
 | 
			
		||||
	qse_size_t msz, i;
 | 
			
		||||
	qse_awk_val_t** va;
 | 
			
		||||
	int x;
 | 
			
		||||
 | 
			
		||||
	nargs = qse_awk_rtx_getnargs(rtx);
 | 
			
		||||
 | 
			
		||||
	a0 = qse_awk_rtx_getarg(rtx, 0);
 | 
			
		||||
	
 | 
			
		||||
	if (QSE_AWK_RTX_GETVALTYPE(rtx, a0) != QSE_AWK_VAL_MAP)
 | 
			
		||||
	a0_type = QSE_AWK_RTX_GETVALTYPE(rtx, a0);
 | 
			
		||||
	QSE_ASSERT (a0_type == QSE_AWK_VAL_REF);
 | 
			
		||||
 | 
			
		||||
	v_type = qse_awk_rtx_getrefvaltype(rtx, (qse_awk_val_ref_t*)a0);
 | 
			
		||||
	if (v_type != QSE_AWK_VAL_MAP)
 | 
			
		||||
	{
 | 
			
		||||
		if (QSE_AWK_RTX_GETVALTYPE(rtx, a0) == QSE_AWK_VAL_NIL)
 | 
			
		||||
		if (v_type == QSE_AWK_VAL_NIL)
 | 
			
		||||
		{
 | 
			
		||||
			/* treat it as an empty value */
 | 
			
		||||
			goto done;
 | 
			
		||||
@ -1565,30 +1587,43 @@ static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	a0_val = qse_awk_rtx_getrefval(rtx, (qse_awk_val_ref_t*)a0);
 | 
			
		||||
	QSE_ASSERT (QSE_AWK_RTX_GETVALTYPE(rtx, a0_val) == QSE_AWK_VAL_MAP);
 | 
			
		||||
 | 
			
		||||
	if (nargs >= 2)
 | 
			
		||||
	{
 | 
			
		||||
		a2 = qse_awk_rtx_getarg(rtx, 2);
 | 
			
		||||
		if (QSE_AWK_RTX_GETVALTYPE(rtx, a2) != QSE_AWK_VAL_FUN)
 | 
			
		||||
		a1 = qse_awk_rtx_getarg(rtx, 1); /* destination map */
 | 
			
		||||
		
 | 
			
		||||
		if (nargs >= 3)
 | 
			
		||||
		{
 | 
			
		||||
			qse_awk_rtx_seterrnum (rtx, QSE_AWK_EINVAL, QSE_NULL);
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
			a2 = qse_awk_rtx_getarg(rtx, 2);
 | 
			
		||||
			if (QSE_AWK_RTX_GETVALTYPE(rtx, a2) != QSE_AWK_VAL_FUN)
 | 
			
		||||
			{
 | 
			
		||||
				qse_awk_rtx_seterrnum (rtx, QSE_AWK_EINVAL, QSE_NULL);
 | 
			
		||||
				return -1;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		fun = ((qse_awk_val_fun_t*)a2)->fun;
 | 
			
		||||
		if (fun->nargs < 2) 
 | 
			
		||||
		{
 | 
			
		||||
			/* the comparison accepts less than 2 arguments */
 | 
			
		||||
			qse_awk_rtx_seterrnum (rtx, QSE_AWK_EINVAL, QSE_NULL);
 | 
			
		||||
			return -1;
 | 
			
		||||
			fun = ((qse_awk_val_fun_t*)a2)->fun;
 | 
			
		||||
			if (fun->nargs < 2) 
 | 
			
		||||
			{
 | 
			
		||||
				/* the comparison accepts less than 2 arguments */
 | 
			
		||||
				qse_awk_rtx_seterrnum (rtx, QSE_AWK_EINVAL, QSE_NULL);
 | 
			
		||||
				return -1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		a1 = a0; /* let a0 be the destination. a0 is both source and destination */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!qse_awk_rtx_getfirstmapvalitr(rtx, a0, &itr)) goto done; /* map empty */
 | 
			
		||||
 | 
			
		||||
	msz = qse_htb_getsize(((qse_awk_val_map_t*)a0)->map);
 | 
			
		||||
	if (!qse_awk_rtx_getfirstmapvalitr(rtx, a0_val, &itr)) goto done; /* map empty */
 | 
			
		||||
 | 
			
		||||
	msz = qse_htb_getsize(((qse_awk_val_map_t*)a0_val)->map);
 | 
			
		||||
	QSE_ASSERT (msz > 0);
 | 
			
		||||
 | 
			
		||||
	va = (qse_awk_val_t**)qse_awk_rtx_allocmem(rtx, msz * QSE_SIZEOF(qse_awk_val_t*));
 | 
			
		||||
	va = (qse_awk_val_t**)qse_awk_rtx_allocmem(rtx, msz * QSE_SIZEOF(*va));
 | 
			
		||||
	if (!va) return -1;
 | 
			
		||||
 | 
			
		||||
	i = 0;
 | 
			
		||||
@ -1596,9 +1631,25 @@ static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
 | 
			
		||||
	{
 | 
			
		||||
		va[i++] = (qse_awk_val_t*)QSE_AWK_VAL_MAP_ITR_VAL(&itr);
 | 
			
		||||
	}
 | 
			
		||||
	while (qse_awk_rtx_getnextmapvalitr(rtx, a0, &itr));
 | 
			
		||||
	while (qse_awk_rtx_getnextmapvalitr(rtx, a0_val, &itr));
 | 
			
		||||
 | 
			
		||||
	qse_qsort (va, msz, QSE_SIZEOF(*va), asort_compare, rtx);
 | 
			
		||||
	if (fun)
 | 
			
		||||
	{
 | 
			
		||||
		struct cud_t cud;
 | 
			
		||||
		cud.rtx = rtx;
 | 
			
		||||
		cud.fun = fun;
 | 
			
		||||
		x = qse_qsortx(va, msz, QSE_SIZEOF(*va), asort_compare_ud, &cud);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		x = qse_qsortx(va, msz, QSE_SIZEOF(*va), asort_compare, rtx);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (x <= -1)
 | 
			
		||||
	{
 | 
			
		||||
		qse_awk_rtx_freemem (rtx, va);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rmap = qse_awk_rtx_makemapval(rtx);
 | 
			
		||||
	if (!rmap) 
 | 
			
		||||
@ -1622,7 +1673,7 @@ static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
 | 
			
		||||
			QSE_NULL
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		if (qse_awk_rtx_setmapvalfld (rtx, rmap, ridx, ridx_len, va[i]) == QSE_NULL)
 | 
			
		||||
		if (qse_awk_rtx_setmapvalfld(rtx, rmap, ridx, ridx_len, va[i]) == QSE_NULL)
 | 
			
		||||
		{
 | 
			
		||||
			qse_awk_rtx_freeval (rtx, rmap, 0);
 | 
			
		||||
			qse_awk_rtx_freemem (rtx, va);
 | 
			
		||||
@ -1630,30 +1681,13 @@ static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
	#if 0
 | 
			
		||||
		/* TODO: complete this function */
 | 
			
		||||
		r = qse_awk_rtx_callfun(rtx, fun, valargs, nargs);
 | 
			
		||||
		if (qse_awk_rtx_valtoint(rtx, r,  &rv) <= -1) return -1;
 | 
			
		||||
 | 
			
		||||
		if (rv > 0)
 | 
			
		||||
		{
 | 
			
		||||
		}
 | 
			
		||||
		else if (rv < 0)
 | 
			
		||||
		{
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
		}
 | 
			
		||||
	#endif
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rv = msz;
 | 
			
		||||
	qse_awk_rtx_freemem (rtx, va);
 | 
			
		||||
/* TODO: set the resulting map back to a0.
 | 
			
		||||
 *       or to a1 if a1 is given */
 | 
			
		||||
qse_awk_rtx_setretval (rtx, rmap);
 | 
			
		||||
return 0;
 | 
			
		||||
 | 
			
		||||
	qse_awk_rtx_refupval (rtx, rmap);
 | 
			
		||||
	x = qse_awk_rtx_setrefval (rtx, (qse_awk_val_ref_t*)a1, rmap);
 | 
			
		||||
	qse_awk_rtx_refdownval (rtx, rmap);
 | 
			
		||||
	if (x <= -1) return -1;
 | 
			
		||||
 | 
			
		||||
done:
 | 
			
		||||
	r = qse_awk_rtx_makeintval(rtx, rv);
 | 
			
		||||
 | 
			
		||||
@ -1650,7 +1650,7 @@ qse_awk_val_t* qse_awk_rtx_callfun (
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		/* thr return value captured in termination by exit()
 | 
			
		||||
		/* the return value captured in termination by exit()
 | 
			
		||||
		 * is reference-counted up in capture_retval_on_exit().
 | 
			
		||||
		 * let's do the same thing for the return value normally
 | 
			
		||||
		 * returned. */
 | 
			
		||||
@ -5996,7 +5996,7 @@ static qse_awk_val_t* __eval_call (
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* push all arguments onto the stack */
 | 
			
		||||
	nargs = argpusher (run, call, apdata);
 | 
			
		||||
	nargs = argpusher(run, call, apdata);
 | 
			
		||||
	if (nargs == (qse_size_t)-1)
 | 
			
		||||
	{
 | 
			
		||||
		UNWIND_RTX_STACK_BASE (run);
 | 
			
		||||
@ -6049,7 +6049,7 @@ static qse_awk_val_t* __eval_call (
 | 
			
		||||
		{
 | 
			
		||||
			run->errinf.num = QSE_AWK_ENOERR;
 | 
			
		||||
 | 
			
		||||
			n = call->u.fnc.spec.impl (run, &call->u.fnc.info);
 | 
			
		||||
			n = call->u.fnc.spec.impl(run, &call->u.fnc.info);
 | 
			
		||||
 | 
			
		||||
			if (n <= -1)
 | 
			
		||||
			{
 | 
			
		||||
 | 
			
		||||
@ -1911,6 +1911,69 @@ qse_awk_int_t qse_awk_rtx_hashval (qse_awk_rtx_t* rtx, qse_awk_val_t* v)
 | 
			
		||||
	return hv  & ~(((qse_awk_uint_t)1) << ((QSE_SIZEOF(qse_awk_uint_t) * 8) - 1));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
qse_awk_val_type_t qse_awk_rtx_getrefvaltype (qse_awk_rtx_t* rtx, qse_awk_val_ref_t* ref)
 | 
			
		||||
{
 | 
			
		||||
	/* return the type of the value that the reference points to */
 | 
			
		||||
	switch (ref->id)
 | 
			
		||||
	{
 | 
			
		||||
		case QSE_AWK_VAL_REF_POS:
 | 
			
		||||
		{
 | 
			
		||||
			return QSE_AWK_VAL_STR;
 | 
			
		||||
		}
 | 
			
		||||
		case QSE_AWK_VAL_REF_GBL:
 | 
			
		||||
		{
 | 
			
		||||
			qse_size_t idx;
 | 
			
		||||
			qse_awk_val_t* v;
 | 
			
		||||
			idx = (qse_size_t)ref->adr;
 | 
			
		||||
			v = RTX_STACK_GBL(rtx, idx);
 | 
			
		||||
			return QSE_AWK_RTX_GETVALTYPE(rtx, v);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		default:
 | 
			
		||||
		{
 | 
			
		||||
			qse_awk_val_t** xref = (qse_awk_val_t**)ref->adr;
 | 
			
		||||
			qse_awk_val_t* v;
 | 
			
		||||
 | 
			
		||||
			/* A reference value is not able to point to another 
 | 
			
		||||
			 * refernce value for the way values are represented
 | 
			
		||||
			 * in QSEAWK */
 | 
			
		||||
			v = *xref;
 | 
			
		||||
			QSE_ASSERT (QSE_AWK_RTX_GETVALTYPE(rtx, v) != QSE_AWK_VAL_REF); 
 | 
			
		||||
			return QSE_AWK_RTX_GETVALTYPE(rtx, v);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
qse_awk_val_t* qse_awk_rtx_getrefval (qse_awk_rtx_t* rtx, qse_awk_val_ref_t* ref)
 | 
			
		||||
{
 | 
			
		||||
	switch (ref->id)
 | 
			
		||||
	{
 | 
			
		||||
		case QSE_AWK_VAL_REF_POS:
 | 
			
		||||
		{
 | 
			
		||||
			/* a positional doesn't contain a value. you should use qse_awk_rtx_valtoXXX()
 | 
			
		||||
			 * like qse_awk_rtx_valtostr(), qse_Awk_rtx_valtoint() */
 | 
			
		||||
			return QSE_NULL;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		case QSE_AWK_VAL_REF_GBL:
 | 
			
		||||
		{
 | 
			
		||||
			qse_size_t idx;
 | 
			
		||||
			idx = (qse_size_t)ref->adr;
 | 
			
		||||
			return RTX_STACK_GBL(rtx, idx);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		default:
 | 
			
		||||
		{
 | 
			
		||||
			qse_awk_val_t** xref = (qse_awk_val_t**)ref->adr;
 | 
			
		||||
			/* A reference value is not able to point to another 
 | 
			
		||||
			 * refernce value for the way values are represented
 | 
			
		||||
			 * in QSEAWK */
 | 
			
		||||
			QSE_ASSERT (QSE_AWK_RTX_GETVALTYPE (rtx, *xref)!= QSE_AWK_VAL_REF); 
 | 
			
		||||
			return *xref;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int qse_awk_rtx_setrefval (qse_awk_rtx_t* rtx, qse_awk_val_ref_t* ref, qse_awk_val_t* val)
 | 
			
		||||
{
 | 
			
		||||
	qse_awk_val_type_t vtype = QSE_AWK_RTX_GETVALTYPE (rtx, val);
 | 
			
		||||
@ -2001,7 +2064,7 @@ int qse_awk_rtx_setrefval (qse_awk_rtx_t* rtx, qse_awk_val_ref_t* ref, qse_awk_v
 | 
			
		||||
			qse_awk_val_type_t rref_vtype;
 | 
			
		||||
 | 
			
		||||
			rref = (qse_awk_val_t**)ref->adr; /* old value pointer */
 | 
			
		||||
			rref_vtype = QSE_AWK_RTX_GETVALTYPE (rtx, *rref); /* old value type */
 | 
			
		||||
			rref_vtype = QSE_AWK_RTX_GETVALTYPE(rtx, *rref); /* old value type */
 | 
			
		||||
			if (vtype == QSE_AWK_VAL_MAP)
 | 
			
		||||
			{
 | 
			
		||||
				/* new value: map, old value: nil or map => ok */
 | 
			
		||||
 | 
			
		||||
@ -64,8 +64,8 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
 | 
			
		||||
 */
 | 
			
		||||
#define swapcode(TYPE,parmi,parmj,n) { \
 | 
			
		||||
	qse_size_t i = (n) / sizeof (TYPE); \
 | 
			
		||||
#define swapcode(TYPE,parmi,parmj,n) do { \
 | 
			
		||||
	qse_size_t i = (n) / QSE_SIZEOF (TYPE); \
 | 
			
		||||
	register TYPE *pi = (TYPE*)(parmi); \
 | 
			
		||||
	register TYPE *pj = (TYPE*)(parmj); \
 | 
			
		||||
	do { 						\
 | 
			
		||||
@ -73,29 +73,38 @@
 | 
			
		||||
		*pi++ = *pj;	\
 | 
			
		||||
		*pj++ = t;		\
 | 
			
		||||
	} while (--i > 0);	\
 | 
			
		||||
}
 | 
			
		||||
} while(0)
 | 
			
		||||
 | 
			
		||||
#define SWAPINIT(a,size) \
 | 
			
		||||
	swaptype = ((qse_byte_t*)a-(qse_byte_t*)0)%sizeof(long) || \
 | 
			
		||||
	           size % sizeof(long) ? 2 : size == sizeof(long)? 0 : 1;
 | 
			
		||||
 | 
			
		||||
static QSE_INLINE void swapfunc (
 | 
			
		||||
	qse_byte_t* a, qse_byte_t* b, int n, int swaptype)
 | 
			
		||||
{
 | 
			
		||||
	if (swaptype <= 1) 
 | 
			
		||||
		swapcode(long, a, b, n)
 | 
			
		||||
	else
 | 
			
		||||
		swapcode(qse_byte_t, a, b, n)
 | 
			
		||||
}
 | 
			
		||||
#define get_swaptype(a, elemsize) (((qse_byte_t*)(a) - (qse_byte_t*)0) % QSE_SIZEOF(long) || elemsize % QSE_SIZEOF(long)? 2 : elemsize == QSE_SIZEOF(long)? 0 : 1)
 | 
			
		||||
 | 
			
		||||
#define swap(a, b) \
 | 
			
		||||
	if (swaptype == 0) { \
 | 
			
		||||
		long t = *(long*)(a); \
 | 
			
		||||
		*(long*)(a) = *(long*)(b); \
 | 
			
		||||
		*(long*)(b) = t; \
 | 
			
		||||
	} else swapfunc(a, b, size, swaptype)
 | 
			
		||||
 | 
			
		||||
#define vecswap(a,b,n) if ((n) > 0) swapfunc(a, b, n, swaptype)
 | 
			
		||||
#define swap(a, b, elemsize) do { \
 | 
			
		||||
	switch (swaptype) \
 | 
			
		||||
	{ \
 | 
			
		||||
		case 0: \
 | 
			
		||||
		{ \
 | 
			
		||||
			long t = *(long*)(a); \
 | 
			
		||||
			*(long*)(a) = *(long*)(b); \
 | 
			
		||||
			*(long*)(b) = t; \
 | 
			
		||||
			break; \
 | 
			
		||||
		} \
 | 
			
		||||
		case 1: \
 | 
			
		||||
			swapcode(long, a, b, elemsize); \
 | 
			
		||||
			break; \
 | 
			
		||||
		default: \
 | 
			
		||||
			swapcode(qse_byte_t, a, b, elemsize); \
 | 
			
		||||
			break; \
 | 
			
		||||
	} \
 | 
			
		||||
} while(0)
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
#define vecswap(a,b,n) do {  \
 | 
			
		||||
	if ((n) > 0)  \
 | 
			
		||||
	{ \
 | 
			
		||||
		if (swaptype <= 1) swapcode(long, a, b, n); \
 | 
			
		||||
		else swapcode(qse_byte_t, a, b, n);  \
 | 
			
		||||
	} \
 | 
			
		||||
} while(0)
 | 
			
		||||
 | 
			
		||||
static QSE_INLINE qse_byte_t* med3 (qse_byte_t* a, qse_byte_t* b, qse_byte_t* c, qse_sort_comper_t comper, void* ctx)
 | 
			
		||||
{
 | 
			
		||||
@ -111,26 +120,48 @@ static QSE_INLINE qse_byte_t* med3 (qse_byte_t* a, qse_byte_t* b, qse_byte_t* c,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static QSE_INLINE qse_byte_t* med3x (qse_byte_t* a, qse_byte_t* b, qse_byte_t* c, qse_sort_comperx_t comper, void* ctx)
 | 
			
		||||
{
 | 
			
		||||
	int n;
 | 
			
		||||
 | 
			
		||||
	if (comper(a, b, ctx, &n) <= -1) return QSE_NULL;
 | 
			
		||||
	if (n < 0)
 | 
			
		||||
	{
 | 
			
		||||
		if (comper(b, c, ctx, &n) <= -1) return QSE_NULL;
 | 
			
		||||
		if (n < 0) return b;
 | 
			
		||||
 | 
			
		||||
		if (comper(a, c, ctx, &n) <= -1) return QSE_NULL;
 | 
			
		||||
		return (n < 0)? c: a;
 | 
			
		||||
	}
 | 
			
		||||
	else 
 | 
			
		||||
	{
 | 
			
		||||
		if (comper(b, c, ctx, &n) <= -1) return QSE_NULL;
 | 
			
		||||
		if (n > 0) return b;
 | 
			
		||||
		if (comper(a, c, ctx, &n) <= -1) return QSE_NULL;
 | 
			
		||||
		return (n > 0)? c: a;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void qse_qsort (void* base, qse_size_t nmemb, qse_size_t size, qse_sort_comper_t comper, void* ctx)
 | 
			
		||||
{
 | 
			
		||||
	qse_byte_t*pa, *pb, *pc, *pd, *pl, *pm, *pn;
 | 
			
		||||
	qse_byte_t* pa, * pb, * pc, * pd, * pl, * pm, * pn;
 | 
			
		||||
	int swaptype, swap_cnt;
 | 
			
		||||
	long r;
 | 
			
		||||
	qse_size_t d;
 | 
			
		||||
	register qse_byte_t*a = (qse_byte_t*)base;
 | 
			
		||||
	register qse_byte_t* a = (qse_byte_t*)base;
 | 
			
		||||
 | 
			
		||||
loop:	
 | 
			
		||||
	SWAPINIT(a, size);
 | 
			
		||||
	swaptype = get_swaptype(a, size);
 | 
			
		||||
 | 
			
		||||
	swap_cnt = 0;
 | 
			
		||||
	if (nmemb < 7) 
 | 
			
		||||
	{
 | 
			
		||||
		for (pm = (qse_byte_t*)a + size;
 | 
			
		||||
		     pm < (qse_byte_t*) a + nmemb * size; pm += size)
 | 
			
		||||
		qse_byte_t* end = (qse_byte_t*)a + (nmemb * size);
 | 
			
		||||
		for (pm = (qse_byte_t*)a + size; pm < end; pm += size)
 | 
			
		||||
		{
 | 
			
		||||
			for (pl = pm; pl > (qse_byte_t*)a && comper(pl - size, pl, ctx) > 0; pl -= size)
 | 
			
		||||
			{
 | 
			
		||||
				swap(pl, pl - size);
 | 
			
		||||
				swap(pl, pl - size, size);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return;
 | 
			
		||||
@ -149,7 +180,7 @@ loop:
 | 
			
		||||
		}
 | 
			
		||||
		pm = med3(pl, pm, pn, comper, ctx);
 | 
			
		||||
	}
 | 
			
		||||
	swap(a, pm);
 | 
			
		||||
	swap(a, pm, size);
 | 
			
		||||
	pa = pb = (qse_byte_t*)a + size;
 | 
			
		||||
 | 
			
		||||
	pc = pd = (qse_byte_t*)a + (nmemb - 1) * size;
 | 
			
		||||
@ -160,7 +191,7 @@ loop:
 | 
			
		||||
			if (r == 0) 
 | 
			
		||||
			{
 | 
			
		||||
				swap_cnt = 1;
 | 
			
		||||
				swap(pa, pb);
 | 
			
		||||
				swap(pa, pb, size);
 | 
			
		||||
				pa += size;
 | 
			
		||||
			}
 | 
			
		||||
			pb += size;
 | 
			
		||||
@ -170,13 +201,13 @@ loop:
 | 
			
		||||
			if (r == 0) 
 | 
			
		||||
			{
 | 
			
		||||
				swap_cnt = 1;
 | 
			
		||||
				swap(pc, pd);
 | 
			
		||||
				swap(pc, pd, size);
 | 
			
		||||
				pd -= size;
 | 
			
		||||
			}
 | 
			
		||||
			pc -= size;
 | 
			
		||||
		}
 | 
			
		||||
		if (pb > pc) break;
 | 
			
		||||
		swap (pb, pc);
 | 
			
		||||
		swap (pb, pc, size);
 | 
			
		||||
		swap_cnt = 1;
 | 
			
		||||
		pb += size;
 | 
			
		||||
		pc -= size;
 | 
			
		||||
@ -188,10 +219,9 @@ loop:
 | 
			
		||||
		for (pm = (qse_byte_t*)a + size; 
 | 
			
		||||
		     pm < (qse_byte_t*)a + nmemb * size; pm += size)
 | 
			
		||||
		{
 | 
			
		||||
			for (pl = pm; pl > (qse_byte_t*)a && 
 | 
			
		||||
			              comper(pl - size, pl, ctx) > 0; pl -= size)
 | 
			
		||||
			for (pl = pm; pl > (qse_byte_t*)a && comper(pl - size, pl, ctx) > 0; pl -= size)
 | 
			
		||||
			{
 | 
			
		||||
				swap(pl, pl - size);
 | 
			
		||||
				swap(pl, pl - size, size);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return;
 | 
			
		||||
@ -215,6 +245,134 @@ loop:
 | 
			
		||||
/*	qsort(pn - r, r / size, size, comper);*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int qse_qsortx (void* base, qse_size_t nmemb, qse_size_t size, qse_sort_comperx_t comper, void* ctx)
 | 
			
		||||
{
 | 
			
		||||
	qse_byte_t* pa, * pb, * pc, * pd, * pl, * pm, * pn;
 | 
			
		||||
	int swaptype, swap_cnt;
 | 
			
		||||
	long r;
 | 
			
		||||
	int n;
 | 
			
		||||
	qse_size_t d;
 | 
			
		||||
	register qse_byte_t* a = (qse_byte_t*)base;
 | 
			
		||||
 | 
			
		||||
loop:	
 | 
			
		||||
	swaptype = get_swaptype(a, size);
 | 
			
		||||
 | 
			
		||||
	swap_cnt = 0;
 | 
			
		||||
	if (nmemb < 7) 
 | 
			
		||||
	{
 | 
			
		||||
		qse_byte_t* end = (qse_byte_t*)a + (nmemb * size);
 | 
			
		||||
		for (pm = (qse_byte_t*)a + size; pm < end; pm += size)
 | 
			
		||||
		{
 | 
			
		||||
			pl = pm;
 | 
			
		||||
			while (pl > (qse_byte_t*)a)
 | 
			
		||||
			{
 | 
			
		||||
				qse_byte_t* pl2 = pl - size;
 | 
			
		||||
				if (comper(pl2, pl, ctx, &n) <= -1) return -1;
 | 
			
		||||
				if (n <= 0) break;
 | 
			
		||||
				swap (pl, pl2, size);
 | 
			
		||||
				pl = pl2;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	pm = (qse_byte_t*)a + (nmemb / 2) * size;
 | 
			
		||||
	if (nmemb > 7) 
 | 
			
		||||
	{
 | 
			
		||||
		pl = (qse_byte_t*)a;
 | 
			
		||||
		pn = (qse_byte_t*)a + (nmemb - 1) * size;
 | 
			
		||||
		if (nmemb > 40) 
 | 
			
		||||
		{
 | 
			
		||||
			d = (nmemb / 8) * size;
 | 
			
		||||
			pl = med3x(pl, pl + d, pl + 2 * d, comper, ctx);
 | 
			
		||||
			if (!pl) return -1;
 | 
			
		||||
			pm = med3x(pm - d, pm, pm + d, comper, ctx);
 | 
			
		||||
			if (!pm) return -1;
 | 
			
		||||
			pn = med3x(pn - 2 * d, pn - d, pn, comper, ctx);
 | 
			
		||||
			if (!pn) return -1;
 | 
			
		||||
		}
 | 
			
		||||
		pm = med3x(pl, pm, pn, comper, ctx);
 | 
			
		||||
		if (!pm) return -1;
 | 
			
		||||
	}
 | 
			
		||||
	swap(a, pm, size);
 | 
			
		||||
	pa = pb = (qse_byte_t*)a + size;
 | 
			
		||||
 | 
			
		||||
	pc = pd = (qse_byte_t*)a + (nmemb - 1) * size;
 | 
			
		||||
	for (;;) 
 | 
			
		||||
	{
 | 
			
		||||
		while (pb <= pc)
 | 
			
		||||
		{
 | 
			
		||||
			if (comper(pb, a, ctx, &n) <= -1) return -1;
 | 
			
		||||
			if (n > 0) break;
 | 
			
		||||
 | 
			
		||||
			if (n == 0) 
 | 
			
		||||
			{
 | 
			
		||||
				swap_cnt = 1;
 | 
			
		||||
				swap(pa, pb, size);
 | 
			
		||||
				pa += size;
 | 
			
		||||
			}
 | 
			
		||||
			pb += size;
 | 
			
		||||
		}
 | 
			
		||||
		while (pb <= pc)
 | 
			
		||||
		{
 | 
			
		||||
			if (comper(pc, a, ctx, &n) <= -1) return -1;
 | 
			
		||||
			if (n < 0) break;
 | 
			
		||||
 | 
			
		||||
			if (n == 0) 
 | 
			
		||||
			{
 | 
			
		||||
				swap_cnt = 1;
 | 
			
		||||
				swap(pc, pd, size);
 | 
			
		||||
				pd -= size;
 | 
			
		||||
			}
 | 
			
		||||
			pc -= size;
 | 
			
		||||
		}
 | 
			
		||||
		if (pb > pc) break;
 | 
			
		||||
		swap (pb, pc, size);
 | 
			
		||||
		swap_cnt = 1;
 | 
			
		||||
		pb += size;
 | 
			
		||||
		pc -= size;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (swap_cnt == 0) 
 | 
			
		||||
	{
 | 
			
		||||
		/* switch to insertion sort */
 | 
			
		||||
		qse_byte_t* end = (qse_byte_t*)a + (nmemb * size);
 | 
			
		||||
		for (pm = (qse_byte_t*)a + size; pm < end; pm += size)
 | 
			
		||||
		{
 | 
			
		||||
			pl = pm;
 | 
			
		||||
			while (pl > (qse_byte_t*)a)
 | 
			
		||||
			{
 | 
			
		||||
				if (comper(pl - size, pl, ctx, &n) <= -1) return -1;
 | 
			
		||||
				if (n <= 0) break;
 | 
			
		||||
				swap(pl, pl - size, size);
 | 
			
		||||
				pl = pl - size;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pn = (qse_byte_t*)a + nmemb * size;
 | 
			
		||||
	r = qsort_min(pa - (qse_byte_t*)a, pb - pa);
 | 
			
		||||
	vecswap (a, pb - r, r);
 | 
			
		||||
	r = qsort_min (pd - pc, pn - pd - size);
 | 
			
		||||
	vecswap (pb, pn - r, r);
 | 
			
		||||
 | 
			
		||||
	if ((r = pb - pa) > size) 
 | 
			
		||||
	{
 | 
			
		||||
		if (qse_qsortx(a, r / size, size, comper, ctx) <= -1) return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((r = pd - pc) > size) 
 | 
			
		||||
	{
 | 
			
		||||
		/* Iterate rather than recurse to save stack space */
 | 
			
		||||
		a = pn - r;
 | 
			
		||||
		nmemb = r / size;
 | 
			
		||||
		goto loop;
 | 
			
		||||
	}
 | 
			
		||||
/*	qsortx(pn - r, r / size, size, comper);*/
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
 | 
			
		||||
/* 
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user