added QSE_AWK_MOD_INT and QSE_AWK_MOD_FLT
added qse_awk_mod_sym_int_t and qse_awk_mod_sym_flt_t
This commit is contained in:
		@ -7,6 +7,7 @@
 | 
			
		||||
 - @ref awk_ext_teq       "TEQ OPERATOR"
 | 
			
		||||
 - @ref awk_ext_vardecl   "VARIABLE DECLARATION"
 | 
			
		||||
 - @ref awk_ext_include   "INCLUDE"
 | 
			
		||||
 - @ref awk_ext_funcall   "FUNCTION CALL"
 | 
			
		||||
 - @ref awk_ext_print     "EXTENDED PRINT/PRINTF"
 | 
			
		||||
 - @ref awk_ext_exprgroup "GROUPED EXPRESSION"
 | 
			
		||||
 - @ref awk_ext_rwpipe    "TWO-WAY PIPE"
 | 
			
		||||
@ -21,6 +22,7 @@
 | 
			
		||||
 - @ref awk_ext_ioenc     "I/O ENCODING"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@section awk_intro INTRODUCTION
 | 
			
		||||
 | 
			
		||||
QSEAWK is an AWK interpreter and is a part of the @ref qse_intro "QSE" library. 
 | 
			
		||||
@ -379,6 +381,33 @@ BEGIN { func_in_abc(); }
 | 
			
		||||
If #QSE_AWK_NEWLINE is off, the semicolon is required.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@subsection awk_ext_funcall FUNCTIONC CALL
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
name(1);
 | 
			
		||||
if there is no space between 'name' and the left parenthesis, the 
 | 
			
		||||
name is treated as a function name.
 | 
			
		||||
 | 
			
		||||
name (1);
 | 
			
		||||
If there is a space, the name is treated as a function name if the 
 | 
			
		||||
name has been declared as the function or if #QSE_AWK_IMPLICIT is on,
 | 
			
		||||
it may be 'name' concatenated with the expression in the parentheses.
 | 
			
		||||
 | 
			
		||||
The following is a valid program.
 | 
			
		||||
@code
 | 
			
		||||
@pragma implicit off
 | 
			
		||||
BEGIN { name (1); }
 | 
			
		||||
function name(a) { print a; }'
 | 
			
		||||
@endcode
 | 
			
		||||
 | 
			
		||||
However, in this program, the first 'name' becomes a named global variable.
 | 
			
		||||
so the function declaration with 'name' triggers the variable redefinition 
 | 
			
		||||
error.
 | 
			
		||||
@pragma implicit on
 | 
			
		||||
BEGIN { name (1); }
 | 
			
		||||
function name(a) { print a; }'
 | 
			
		||||
@endcode
 | 
			
		||||
 | 
			
		||||
@subsection awk_ext_print EXTENDED PRINT/PRINTF
 | 
			
		||||
When #QSE_AWK_TOLERANT is on, print and printf are treated as if
 | 
			
		||||
they are function calls.  In this mode, they return a negative number
 | 
			
		||||
 | 
			
		||||
@ -754,12 +754,18 @@ struct qse_awk_mod_t
 | 
			
		||||
 | 
			
		||||
enum qse_awk_mod_sym_type_t
 | 
			
		||||
{
 | 
			
		||||
	QSE_AWK_MOD_FNC = 0 /*,
 | 
			
		||||
	QSE_AWK_MOD_VAR */
 | 
			
		||||
	QSE_AWK_MOD_FNC = 0, 
 | 
			
		||||
	QSE_AWK_MOD_INT, /* constant */
 | 
			
		||||
	QSE_AWK_MOD_FLT  /* constant */
 | 
			
		||||
	/*QSE_AWK_MOD_STR,
 | 
			
		||||
	QSE_AWK_MOD_VAR,
 | 
			
		||||
	*/
 | 
			
		||||
};
 | 
			
		||||
typedef enum qse_awk_mod_sym_type_t qse_awk_mod_sym_type_t;
 | 
			
		||||
 | 
			
		||||
typedef struct qse_awk_mod_sym_fnc_t qse_awk_mod_sym_fnc_t;
 | 
			
		||||
typedef struct qse_awk_mod_sym_int_t qse_awk_mod_sym_int_t;
 | 
			
		||||
typedef struct qse_awk_mod_sym_flt_t qse_awk_mod_sym_flt_t;
 | 
			
		||||
 | 
			
		||||
struct qse_awk_mod_sym_fnc_t
 | 
			
		||||
{
 | 
			
		||||
	struct
 | 
			
		||||
@ -770,12 +776,24 @@ struct qse_awk_mod_sym_fnc_t
 | 
			
		||||
	qse_awk_fnc_impl_t impl;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct qse_awk_mod_sym_int_t
 | 
			
		||||
{
 | 
			
		||||
	qse_long_t val;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct qse_awk_mod_sym_flt_t
 | 
			
		||||
{
 | 
			
		||||
	qse_flt_t val;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct qse_awk_mod_sym_t
 | 
			
		||||
{
 | 
			
		||||
	qse_awk_mod_sym_type_t type; 
 | 
			
		||||
	union
 | 
			
		||||
	{
 | 
			
		||||
		qse_awk_mod_sym_fnc_t fnc;
 | 
			
		||||
		qse_awk_mod_sym_int_t in;
 | 
			
		||||
		qse_awk_mod_sym_flt_t flt;
 | 
			
		||||
	} u;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2079,6 +2079,10 @@ static qse_awk_nde_t* parse_if (qse_awk_t* awk, const qse_awk_loc_t* xloc)
 | 
			
		||||
		goto oops;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
/* TODO: optimization. if you know 'tese' evaluates to true or false,
 | 
			
		||||
 *       you can drop the 'if' statement and take either the 'then_part'
 | 
			
		||||
 *       or 'else_part'. */
 | 
			
		||||
 | 
			
		||||
	if (get_token(awk) <= -1) goto oops;
 | 
			
		||||
 | 
			
		||||
	tloc = awk->tok.loc;
 | 
			
		||||
@ -5000,30 +5004,41 @@ static qse_awk_nde_t* parse_primary_ident_segs (
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		if (sym.type == QSE_AWK_MOD_FNC)
 | 
			
		||||
		switch (sym.type)
 | 
			
		||||
		{
 | 
			
		||||
			if (MATCH(awk,TOK_LPAREN))
 | 
			
		||||
			{
 | 
			
		||||
				QSE_MEMSET (&fnc, 0, QSE_SIZEOF(fnc));
 | 
			
		||||
			case QSE_AWK_MOD_FNC:
 | 
			
		||||
				if (MATCH(awk,TOK_LPAREN))
 | 
			
		||||
				{
 | 
			
		||||
					QSE_MEMSET (&fnc, 0, QSE_SIZEOF(fnc));
 | 
			
		||||
					fnc.name.ptr = full->ptr; 
 | 
			
		||||
					fnc.name.len = full->len;
 | 
			
		||||
					fnc.arg.min = sym.u.fnc.arg.min;
 | 
			
		||||
					fnc.arg.max = sym.u.fnc.arg.max;
 | 
			
		||||
					fnc.handler = sym.u.fnc.impl;
 | 
			
		||||
					fnc.mod = mod;
 | 
			
		||||
	
 | 
			
		||||
					nde = parse_fncall (awk, full, &fnc, xloc, 0);
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					SETERR_TOK (awk, QSE_AWK_ELPAREN);
 | 
			
		||||
				}
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
				fnc.name.ptr = full->ptr; 
 | 
			
		||||
				fnc.name.len = full->len;
 | 
			
		||||
				fnc.arg.min = sym.u.fnc.arg.min;
 | 
			
		||||
				fnc.arg.max = sym.u.fnc.arg.max;
 | 
			
		||||
				fnc.handler = sym.u.fnc.impl;
 | 
			
		||||
				fnc.mod = mod;
 | 
			
		||||
			case QSE_AWK_MOD_INT:
 | 
			
		||||
				nde = new_int_node (awk, sym.u.in.val, xloc);
 | 
			
		||||
				/* i don't remember the symbol in the original form */
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
				nde = parse_fncall (awk, full, &fnc, xloc, 0);
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				SETERR_TOK (awk, QSE_AWK_ELPAREN);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{ 
 | 
			
		||||
			/* TODO: support MOD_VAR */
 | 
			
		||||
			SETERR_ARG_LOC (awk, QSE_AWK_EUNDEF, full->ptr, full->len, xloc);
 | 
			
		||||
			case QSE_AWK_MOD_FLT:
 | 
			
		||||
				nde = new_flt_node (awk, sym.u.flt.val, xloc);
 | 
			
		||||
				/* i don't remember the symbol in the original form */
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			default:
 | 
			
		||||
				/* TODO: support MOD_VAR */
 | 
			
		||||
				SETERR_ARG_LOC (awk, QSE_AWK_EUNDEF, full->ptr, full->len, xloc);
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -45,14 +45,10 @@ static int fnc_fork (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
 | 
			
		||||
 | 
			
		||||
static int fnc_wait (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
 | 
			
		||||
{
 | 
			
		||||
	qse_size_t nargs;
 | 
			
		||||
	qse_long_t lv;
 | 
			
		||||
	qse_awk_val_t* retv;
 | 
			
		||||
	int n;
 | 
			
		||||
 | 
			
		||||
	nargs = qse_awk_rtx_getnargs (rtx);
 | 
			
		||||
	QSE_ASSERT (nargs == 1);
 | 
			
		||||
 | 
			
		||||
/* TODO: handle more parameters */
 | 
			
		||||
 | 
			
		||||
	n = qse_awk_rtx_valtolong (rtx, qse_awk_rtx_getarg (rtx, 0), &lv);
 | 
			
		||||
@ -83,7 +79,6 @@ static int fnc_wait (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
 | 
			
		||||
 | 
			
		||||
static int fnc_sleep (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
 | 
			
		||||
{
 | 
			
		||||
	qse_size_t nargs;
 | 
			
		||||
	qse_long_t lv;
 | 
			
		||||
	qse_awk_val_t* retv;
 | 
			
		||||
	int n;
 | 
			
		||||
@ -118,11 +113,23 @@ struct fnctab_t
 | 
			
		||||
	qse_awk_mod_sym_fnc_t info;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct inttab_t inttab_t;
 | 
			
		||||
struct inttab_t
 | 
			
		||||
{
 | 
			
		||||
	const qse_char_t* name;
 | 
			
		||||
	qse_awk_mod_sym_int_t info;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static fnctab_t fnctab[] =
 | 
			
		||||
{
 | 
			
		||||
	{ QSE_T("fork"),  { { 0, 0 }, fnc_fork } },
 | 
			
		||||
	{ QSE_T("sleep"), { { 1, 1 }, fnc_sleep  } },
 | 
			
		||||
	{ QSE_T("wait"),  { { 1, 1 }, fnc_wait  } }
 | 
			
		||||
	{ QSE_T("fork"),    { { 0, 0 }, fnc_fork } },
 | 
			
		||||
	{ QSE_T("sleep"),   { { 1, 1 }, fnc_sleep  } },
 | 
			
		||||
	{ QSE_T("wait"),    { { 1, 1 }, fnc_wait  } }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static inttab_t inttab[] =
 | 
			
		||||
{
 | 
			
		||||
	{ QSE_T("WNOHANG"), { WNOHANG } }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int query (qse_awk_mod_t* mod, qse_awk_t* awk, const qse_char_t* name, qse_awk_mod_sym_t* sym)
 | 
			
		||||
@ -130,7 +137,7 @@ static int query (qse_awk_mod_t* mod, qse_awk_t* awk, const qse_char_t* name, qs
 | 
			
		||||
	qse_cstr_t ea;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
/* TODO: binary search */
 | 
			
		||||
/* TODO: binary search or something better */
 | 
			
		||||
	for (i = 0; i < QSE_COUNTOF(fnctab); i++)
 | 
			
		||||
	{
 | 
			
		||||
		if (qse_strcmp (fnctab[i].name, name) == 0)
 | 
			
		||||
@ -141,14 +148,15 @@ static int query (qse_awk_mod_t* mod, qse_awk_t* awk, const qse_char_t* name, qs
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
	if (qse_strcmp (name, QSE_T("WNOHANG")) == 0)
 | 
			
		||||
	for (i = 0; i < QSE_COUNTOF(inttab); i++)
 | 
			
		||||
	{
 | 
			
		||||
		sym->type = QSE_AWK_MOD_INTCON;
 | 
			
		||||
		sym->u.c.ivalue = WNOHANG;
 | 
			
		||||
		return 0;
 | 
			
		||||
		if (qse_strcmp (inttab[i].name, name) == 0)
 | 
			
		||||
		{
 | 
			
		||||
			sym->type = QSE_AWK_MOD_INT;
 | 
			
		||||
			sym->u.in = inttab[i].info;
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
	ea.ptr = name;
 | 
			
		||||
	ea.len = qse_strlen(name);
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user