amended the reference handling in Awk.cpp.
added str::index() and str::rindex(). enhanded qse_awk_rtx_valtobool(). removed QSE_AWK_NCMPONSTR from QSE_AWK_CLASSIC. added QSE_AWK_NCMPONSTR to QSE_AWK_MODERN.
This commit is contained in:
parent
23d316a659
commit
3d813a1bf1
@ -234,8 +234,9 @@ struct qse_awk_val_ref_t
|
||||
QSE_AWK_VAL_REF_POS /**< positional variable */
|
||||
} id;
|
||||
|
||||
/* if id is QSE_AWK_VAL_REF_POS, adr holds an index of the
|
||||
* positional variable. Otherwise, adr points to the value
|
||||
/* if id is QSE_AWK_VAL_REF_POS, adr holds the index of a
|
||||
* positional variable. If id is QSE_AWK_VAL_REF_GBL, adr hold
|
||||
* the index of a global variable. Otherwise, adr points to the value
|
||||
* directly. */
|
||||
qse_awk_val_t** adr;
|
||||
};
|
||||
@ -1124,11 +1125,11 @@ enum qse_awk_trait_t
|
||||
QSE_AWK_CLASSIC =
|
||||
QSE_AWK_IMPLICIT | QSE_AWK_RIO |
|
||||
QSE_AWK_NEWLINE | QSE_AWK_BLANKCONCAT | QSE_AWK_PABLOCK |
|
||||
QSE_AWK_STRIPSTRSPC | QSE_AWK_NCMPONSTR | QSE_AWK_STRICTNAMING,
|
||||
QSE_AWK_STRIPSTRSPC | QSE_AWK_STRICTNAMING,
|
||||
|
||||
QSE_AWK_MODERN =
|
||||
QSE_AWK_CLASSIC | QSE_AWK_FLEXMAP |
|
||||
QSE_AWK_RWPIPE | QSE_AWK_TOLERANT | QSE_AWK_NEXTOFILE
|
||||
QSE_AWK_RWPIPE | QSE_AWK_TOLERANT | QSE_AWK_NEXTOFILE | QSE_AWK_NCMPONSTR
|
||||
};
|
||||
typedef enum qse_awk_trait_t qse_awk_trait_t;
|
||||
|
||||
|
@ -1392,7 +1392,9 @@ int Awk::dispatch_function (Run* run, const fnc_info_t* fi)
|
||||
{
|
||||
qse_awk_val_ref_t* ref = (qse_awk_val_ref_t*)v;
|
||||
|
||||
if (ref->id == qse_awk_val_ref_t::QSE_AWK_VAL_REF_POS)
|
||||
switch (ref->id)
|
||||
{
|
||||
case qse_awk_val_ref_t::QSE_AWK_VAL_REF_POS:
|
||||
{
|
||||
qse_size_t idx = (qse_size_t)ref->adr;
|
||||
|
||||
@ -1412,10 +1414,20 @@ int Awk::dispatch_function (Run* run, const fnc_info_t* fi)
|
||||
{
|
||||
xx = args[i].setStr (run, QSE_T(""), 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
||||
case qse_awk_val_ref_t::QSE_AWK_VAL_REF_GBL:
|
||||
{
|
||||
qse_size_t idx = (qse_size_t)ref->adr;
|
||||
qse_awk_val_t* val = (qse_awk_val_t*)RTX_STACK_GBL (run->rtx, idx);
|
||||
xx = args[i].setVal (run, val);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
xx = args[i].setVal (run, *(ref->adr));
|
||||
break;
|
||||
}
|
||||
has_ref_arg = true;
|
||||
}
|
||||
|
@ -76,6 +76,106 @@ static int fnc_rtrim (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
||||
return trim (rtx, QSE_STRTRMX_RIGHT);
|
||||
}
|
||||
|
||||
static int index_or_rindex (qse_awk_rtx_t* rtx, int rindex)
|
||||
{
|
||||
/* this is similar to the built-in index() function but doesn't
|
||||
* care about IGNORECASE. */
|
||||
qse_size_t nargs;
|
||||
qse_awk_val_t* a0, * a1;
|
||||
qse_char_t* str0, * str1, * ptr;
|
||||
qse_size_t len0, len1;
|
||||
qse_long_t idx, boundary = 1;
|
||||
|
||||
nargs = qse_awk_rtx_getnargs (rtx);
|
||||
a0 = qse_awk_rtx_getarg (rtx, 0);
|
||||
a1 = qse_awk_rtx_getarg (rtx, 1);
|
||||
|
||||
/*
|
||||
str::index ("abc", "d", 3);
|
||||
str::rindex ("abcdefabcdx", "cd", 8);
|
||||
*/
|
||||
|
||||
if (nargs >= 3)
|
||||
{
|
||||
qse_awk_val_t* a2;
|
||||
int n;
|
||||
|
||||
a2 = qse_awk_rtx_getarg (rtx, 2);
|
||||
n = qse_awk_rtx_valtolong (rtx, a2, &boundary);
|
||||
if (n <= -1) return -1;
|
||||
}
|
||||
|
||||
if (a0->type == QSE_AWK_VAL_STR)
|
||||
{
|
||||
str0 = ((qse_awk_val_str_t*)a0)->val.ptr;
|
||||
len0 = ((qse_awk_val_str_t*)a0)->val.len;
|
||||
}
|
||||
else
|
||||
{
|
||||
str0 = qse_awk_rtx_valtostrdup (rtx, a0, &len0);
|
||||
if (str0 == QSE_NULL) return -1;
|
||||
}
|
||||
|
||||
if (a1->type == QSE_AWK_VAL_STR)
|
||||
{
|
||||
str1 = ((qse_awk_val_str_t*)a1)->val.ptr;
|
||||
len1 = ((qse_awk_val_str_t*)a1)->val.len;
|
||||
}
|
||||
else
|
||||
{
|
||||
str1 = qse_awk_rtx_valtostrdup (rtx, a1, &len1);
|
||||
if (str1 == QSE_NULL)
|
||||
{
|
||||
if (a0->type != QSE_AWK_VAL_STR)
|
||||
qse_awk_rtx_freemem (rtx, str0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (nargs < 3)
|
||||
{
|
||||
boundary = rindex? len0: 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (boundary == 0) boundary = 1;
|
||||
else if (boundary < 0) boundary = len0 + boundary + 1;
|
||||
}
|
||||
|
||||
if (rindex)
|
||||
{
|
||||
/* 'boundary' acts as an end position */
|
||||
ptr = (boundary > len0 || boundary <= 0)?
|
||||
QSE_NULL: qse_strxnrstr (&str0[0], boundary, str1, len1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 'boundary' acts as a start position */
|
||||
ptr = (boundary > len0 || boundary <= 0)?
|
||||
QSE_NULL: qse_strxnstr (&str0[boundary-1], len0-boundary+1, str1, len1);
|
||||
}
|
||||
|
||||
idx = (ptr == QSE_NULL)? 0: ((qse_long_t)(ptr-str0) + 1);
|
||||
|
||||
if (a0->type != QSE_AWK_VAL_STR) qse_awk_rtx_freemem (rtx, str0);
|
||||
if (a1->type != QSE_AWK_VAL_STR) qse_awk_rtx_freemem (rtx, str1);
|
||||
|
||||
a0 = qse_awk_rtx_makeintval (rtx, idx);
|
||||
if (a0 == QSE_NULL) return -1;
|
||||
|
||||
qse_awk_rtx_setretval (rtx, a0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fnc_index (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
||||
{
|
||||
return index_or_rindex (rtx, 0);
|
||||
}
|
||||
static int fnc_rindex (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
||||
{
|
||||
return index_or_rindex (rtx, 1);
|
||||
}
|
||||
|
||||
typedef struct fnctab_t fnctab_t;
|
||||
struct fnctab_t
|
||||
{
|
||||
@ -86,8 +186,10 @@ struct fnctab_t
|
||||
static fnctab_t fnctab[] =
|
||||
{
|
||||
/* keep this table sorted for binary search in query(). */
|
||||
{ QSE_T("index"), { { 2, 3, QSE_NULL }, fnc_index, 0 } },
|
||||
{ QSE_T("ltrim"), { { 1, 1, QSE_NULL }, fnc_ltrim, 0 } },
|
||||
{ QSE_T("normspace"), { { 1, 1, QSE_NULL }, fnc_normspace, 0 } },
|
||||
{ QSE_T("rindex"), { { 2, 3, QSE_NULL }, fnc_rindex, 0 } },
|
||||
{ QSE_T("rtrim"), { { 1, 1, QSE_NULL }, fnc_rtrim, 0 } },
|
||||
{ QSE_T("trim"), { { 1, 1, QSE_NULL }, fnc_trim, 0 } }
|
||||
};
|
||||
|
@ -913,7 +913,9 @@ void qse_awk_rtx_freevalchunk (qse_awk_rtx_t* rtx, qse_awk_val_chunk_t* chunk)
|
||||
static int val_ref_to_bool (
|
||||
qse_awk_rtx_t* rtx, const qse_awk_val_ref_t* ref)
|
||||
{
|
||||
if (ref->id == QSE_AWK_VAL_REF_POS)
|
||||
switch (ref->id)
|
||||
{
|
||||
case QSE_AWK_VAL_REF_POS:
|
||||
{
|
||||
qse_size_t idx;
|
||||
|
||||
@ -933,7 +935,14 @@ static int val_ref_to_bool (
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
case QSE_AWK_VAL_REF_GBL:
|
||||
{
|
||||
qse_size_t idx;
|
||||
idx = (qse_size_t)ref->adr;
|
||||
return qse_awk_rtx_valtobool (rtx, RTX_STACK_GBL (rtx, idx));
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
qse_awk_val_t** xref = (qse_awk_val_t**)ref->adr;
|
||||
|
||||
@ -946,6 +955,7 @@ static int val_ref_to_bool (
|
||||
return qse_awk_rtx_valtobool (rtx, *xref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int qse_awk_rtx_valtobool (qse_awk_rtx_t* rtx, const qse_awk_val_t* val)
|
||||
@ -1680,7 +1690,7 @@ qse_long_t qse_awk_rtx_hashval (qse_awk_rtx_t* rtx, qse_awk_val_t* v)
|
||||
|
||||
int qse_awk_rtx_setrefval (qse_awk_rtx_t* rtx, qse_awk_val_ref_t* ref, qse_awk_val_t* val)
|
||||
{
|
||||
if (val->type == QSE_AWK_VAL_REX)
|
||||
if (val->type == QSE_AWK_VAL_REX || val->type == QSE_AWK_VAL_REF)
|
||||
{
|
||||
/* though it is possible that an intrinsic function handler
|
||||
* can accept a regular expression withtout evaluation when 'x'
|
||||
|
@ -1 +1,7 @@
|
||||
FNR == 1, FNR == 5 { print FILENAME ": " $0; }
|
||||
function basename (str) {
|
||||
ridx = str::rindex (str, "/");
|
||||
if (ridx == 0) return str;
|
||||
else return substr (str, ridx + 1);
|
||||
}
|
||||
|
||||
FNR == 1, FNR == 5 { print basename(FILENAME) ": " $0; }
|
||||
|
@ -1 +1,6 @@
|
||||
FNR <= 5 { print FILENAME ": " $0; }
|
||||
function basename (str) {
|
||||
ridx = str::rindex (str, "/");
|
||||
if (ridx == 0) return str;
|
||||
else return substr (str, ridx + 1);
|
||||
}
|
||||
FNR <= 5 { print basename(FILENAME) ": " $0; }
|
||||
|
Loading…
Reference in New Issue
Block a user