added qse_awk_rtx_findfun() and qse_awk_rtx_callfun()

This commit is contained in:
hyung-hwan 2011-05-22 10:08:54 +00:00
parent d879fd69af
commit 8f88a97dfc
4 changed files with 152 additions and 17 deletions

View File

@ -1,5 +1,5 @@
/*
* $Id: awk.h 463 2011-05-19 02:50:51Z hyunghwan.chung $
* $Id: awk.h 468 2011-05-21 16:08:54Z hyunghwan.chung $
*
Copyright 2006-2011 Chung, Hyung-Hwan.
This file is part of QSE.
@ -118,6 +118,17 @@ typedef struct qse_awk_t qse_awk_t;
*/
typedef struct qse_awk_rtx_t qse_awk_rtx_t;
/**
* The qse_awk_fun_t type defines an awk function type defined with the
* keyword 'function'.
*/
typedef struct qse_awk_fun_t qse_awk_fun_t;
/**
* The qse_awk_fnc_t type defines an intrisic function type.
*/
typedef struct qse_awk_fnc_t qse_awk_fnc_t;
/**
* The qse_awk_loc_t type defines a structure to hold location.
*/
@ -354,6 +365,7 @@ struct qse_awk_nde_t
QSE_AWK_NDE_HDR;
};
typedef int (*qse_awk_sprintf_t) (
qse_awk_t* awk,
qse_char_t* buf,
@ -1591,8 +1603,30 @@ qse_awk_val_t* qse_awk_rtx_loop (
);
/**
* The qse_awk_rtx_call() function invokes an AWK function. However, it is
* not able to invoke an intrinsic function such as split().
* The qse_awk_rtx_findfun() function finds the function structure by name
* and returns the pointer to it if one is found. It returns #QSE_NULL if
* it fails to find a function by the @a name.
*/
qse_awk_fun_t* qse_awk_rtx_findfun (
qse_awk_rtx_t* rtx, /**< runtime context */
const qse_char_t* name /**< function name */
);
/**
* The qse_awk_rtx_callfun() function invokdes an AWK function described by
* the structure pointed to by @a fun.
* @sa qse_awk_rtx_call
*/
qse_awk_val_t* qse_awk_rtx_callfun (
qse_awk_rtx_t* rtx, /**< runtime context */
qse_awk_fun_t* fun, /**< function */
qse_awk_val_t** args, /**< arguments to the function */
qse_size_t nargs /**< the number of arguments */
);
/**
* The qse_awk_rtx_call() function invokes an AWK function named @a name.
* However, it is not able to invoke an intrinsic function such as split().
* The #QSE_AWK_PABLOCK option can be turned off to make illegal the BEGIN
* block, the pattern-action blocks, and the END block.
*

View File

@ -1,5 +1,5 @@
/*
* $Id: fnc.h 441 2011-04-22 14:28:43Z hyunghwan.chung $
* $Id: fnc.h 468 2011-05-21 16:08:54Z hyunghwan.chung $
*
Copyright 2006-2011 Chung, Hyung-Hwan.
This file is part of QSE.
@ -21,8 +21,6 @@
#ifndef _QSE_LIB_AWK_FNC_H_
#define _QSE_LIB_AWK_FNC_H_
typedef struct qse_awk_fnc_t qse_awk_fnc_t;
struct qse_awk_fnc_t
{
struct

View File

@ -1,5 +1,5 @@
/*
* $Id: run.c 465 2011-05-19 03:46:53Z hyunghwan.chung $
* $Id: run.c 468 2011-05-21 16:08:54Z hyunghwan.chung $
*
Copyright 2006-2011 Chung, Hyung-Hwan.
This file is part of QSE.
@ -1515,11 +1515,115 @@ qse_awk_val_t* qse_awk_rtx_loop (qse_awk_rtx_t* rtx)
return retv;
}
/* call an AWK function */
/* find an AWK function by name */
qse_awk_fun_t* qse_awk_rtx_findfun (qse_awk_rtx_t* rtx, const qse_char_t* name)
{
qse_htb_pair_t* pair;
pair = qse_htb_search (
rtx->awk->tree.funs,
name, qse_strlen(name)
);
if (pair == QSE_NULL)
{
qse_cstr_t nm;
nm.ptr = name;
nm.len = qse_strlen(name);
SETERR_ARGX (rtx, QSE_AWK_EFUNNF, &nm);
return QSE_NULL;
}
return (qse_awk_fun_t*)QSE_HTB_VPTR(pair);
}
/* call an AWK function by the function structure */
qse_awk_val_t* qse_awk_rtx_callfun (
qse_awk_rtx_t* rtx, qse_awk_fun_t* fun,
qse_awk_val_t** args, qse_size_t nargs)
{
struct capture_retval_data_t crdata;
qse_awk_val_t* v;
struct pafv pafv/*= { args, nargs }*/;
qse_awk_nde_call_t call;
QSE_ASSERT (fun != QSE_NULL);
pafv.args = args;
pafv.nargs = nargs;
if (rtx->exit_level >= EXIT_GLOBAL)
{
/* cannot call the function again when exit() is called
* in an AWK program or qse_awk_rtx_stop() is invoked */
SETERR_COD (rtx, QSE_AWK_ENOPER);
return QSE_NULL;
}
/*rtx->exit_level = EXIT_NONE;*/
/* forge a fake node containing a function call */
QSE_MEMSET (&call, 0, QSE_SIZEOF(call));
call.type = QSE_AWK_NDE_FUN;
call.what.fun.name = fun->name;
call.nargs = nargs;
/* check if the number of arguments given is more than expected */
if (nargs > fun->nargs)
{
/* TODO: is this correct? what if i want to
* allow arbitarary numbers of arguments? */
SETERR_COD (rtx, QSE_AWK_EARGTM);
return QSE_NULL;
}
/* now that the function is found and ok, let's execute it */
crdata.rtx = rtx;
crdata.val = QSE_NULL;
v = __eval_call (
rtx, (qse_awk_nde_t*)&call, QSE_NULL, fun,
push_arg_from_vals, (void*)&pafv,
capture_retval_on_exit,
&crdata
);
if (v == QSE_NULL)
{
/* an error occurred. let's check if it is caused by exit().
* if so, the return value should have been captured into
* crdata.val. */
if (crdata.val != QSE_NULL) v = crdata.val; /* yet it is */
}
else
{
/* thr 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. */
qse_awk_rtx_refupval (rtx, v);
}
/* return the return value with its reference count at least 1.
* the caller of this function should count down its reference. */
return v;
}
/* call an AWK function by name */
qse_awk_val_t* qse_awk_rtx_call (
qse_awk_rtx_t* rtx, const qse_char_t* name,
qse_awk_val_t** args, qse_size_t nargs)
{
qse_awk_fun_t* fun;
fun = qse_awk_rtx_findfun (rtx, name);
if (fun == QSE_NULL) return QSE_NULL;
return qse_awk_rtx_callfun (rtx, fun, args, nargs);
#if 0
qse_htb_pair_t* pair;
qse_awk_fun_t* fun;
struct capture_retval_data_t crdata;
@ -1603,6 +1707,7 @@ qse_awk_val_t* qse_awk_rtx_call (
/* return the return value with its reference count at least 1.
* the caller of this function should count down its reference. */
return v;
#endif
}
static int run_pblocks (qse_awk_rtx_t* run)
@ -4788,8 +4893,8 @@ static qse_awk_val_t* eval_binop_match0 (
n = QSE_AWK_MATCHREX (
rtx->awk, rex_code,
((rtx->gbl.ignorecase)? QSE_REX_IGNORECASE: 0),
&((qse_awk_val_str_t*)left)->val,
&((qse_awk_val_str_t*)left)->val,
xstr_to_cstr(&((qse_awk_val_str_t*)left)->val),
xstr_to_cstr(&((qse_awk_val_str_t*)left)->val),
QSE_NULL, &errnum);
if (n == -1)
{
@ -4825,8 +4930,10 @@ static qse_awk_val_t* eval_binop_match0 (
n = QSE_AWK_MATCHREX (
rtx->awk, rex_code,
((rtx->gbl.ignorecase)? QSE_REX_IGNORECASE: 0),
&out.u.cpldup, &out.u.cpldup,
QSE_NULL, &errnum);
xstr_to_cstr(&out.u.cpldup),
xstr_to_cstr(&out.u.cpldup),
QSE_NULL, &errnum
);
if (n == -1)
{
QSE_AWK_FREE (rtx->awk, out.u.cpldup.ptr);

View File

@ -1,5 +1,5 @@
/*
* $Id: tree.h 441 2011-04-22 14:28:43Z hyunghwan.chung $
* $Id: tree.h 468 2011-05-21 16:08:54Z hyunghwan.chung $
*
Copyright 2006-2011 Chung, Hyung-Hwan.
This file is part of QSE.
@ -44,10 +44,6 @@ enum qse_awk_out_type_t
QSE_AWK_OUT_CONSOLE
};
/* AWK function defined with the keyword function.
* note it is different from qse_awk_fnc_t */
typedef struct qse_awk_fun_t qse_awk_fun_t;
typedef struct qse_awk_nde_blk_t qse_awk_nde_blk_t;
typedef struct qse_awk_nde_grp_t qse_awk_nde_grp_t;
typedef struct qse_awk_nde_ass_t qse_awk_nde_ass_t;