enhanced the awk parser

This commit is contained in:
hyung-hwan 2009-08-07 02:27:14 +00:00
parent ff92573543
commit 3fc663609e
10 changed files with 545 additions and 540 deletions

View File

@ -1,5 +1,5 @@
/* /*
* $Id: Awk.hpp 247 2009-07-31 13:01:04Z hyunghwan.chung $ * $Id: Awk.hpp 248 2009-08-06 08:27:14Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
@ -92,9 +92,8 @@ public:
ERR_EXPRNST = QSE_AWK_EEXPRNST, ERR_EXPRNST = QSE_AWK_EEXPRNST,
ERR_LXCHR = QSE_AWK_ELXCHR, ERR_LXCHR = QSE_AWK_ELXCHR,
ERR_LXDIG = QSE_AWK_ELXDIG, ERR_LXDIG = QSE_AWK_ELXDIG,
ERR_LXUNG = QSE_AWK_ELXUNG,
ERR_ENDSRC = QSE_AWK_EENDSRC, ERR_ENDSRC = QSE_AWK_EENDSRC,
ERR_ENDCMT = QSE_AWK_EENDCMT, ERR_ECMNTNC = QSE_AWK_ECMNTNC,
ERR_ENDSTR = QSE_AWK_EENDSTR, ERR_ENDSTR = QSE_AWK_EENDSTR,
ERR_ENDREX = QSE_AWK_EENDREX, ERR_ENDREX = QSE_AWK_EENDREX,
ERR_LBRACE = QSE_AWK_ELBRACE, ERR_LBRACE = QSE_AWK_ELBRACE,

View File

@ -1,5 +1,5 @@
/* /*
* $Id: awk.h 247 2009-07-31 13:01:04Z hyunghwan.chung $ * $Id: awk.h 248 2009-08-06 08:27:14Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
@ -273,7 +273,7 @@ typedef enum qse_awk_sio_cmd_t qse_awk_sio_cmd_t;
struct qse_awk_sio_arg_t struct qse_awk_sio_arg_t
{ {
qse_char_t* name; /**< [IN] name of I/O object */ const qse_char_t* name; /**< [IN] name of I/O object */
void* handle; /**< [OUT] I/O handle set by a handler */ void* handle; /**< [OUT] I/O handle set by a handler */
/*-- from here down, internal use only --*/ /*-- from here down, internal use only --*/
@ -284,12 +284,8 @@ struct qse_awk_sio_arg_t
qse_size_t len; qse_size_t len;
} b; } b;
struct qse_size_t lin;
{ qse_size_t col;
qse_size_t line;
qse_size_t column;
} saved;
struct qse_awk_sio_arg_t* next; struct qse_awk_sio_arg_t* next;
}; };
typedef struct qse_awk_sio_arg_t qse_awk_sio_arg_t; typedef struct qse_awk_sio_arg_t qse_awk_sio_arg_t;
@ -642,10 +638,9 @@ enum qse_awk_errnum_t
QSE_AWK_ELXCHR, /**< invalid character '${0}' */ QSE_AWK_ELXCHR, /**< invalid character '${0}' */
QSE_AWK_ELXDIG, /**< invalid digit '${0}' */ QSE_AWK_ELXDIG, /**< invalid digit '${0}' */
QSE_AWK_ELXUNG, /**< failed to unget character */
QSE_AWK_EENDSRC, /**< unexpected end of source */ QSE_AWK_EENDSRC, /**< unexpected end of source */
QSE_AWK_EENDCMT, /**< comment not closed properly */ QSE_AWK_ECMNTNC, /**< comment not closed properly */
QSE_AWK_EENDSTR, /**< string or regular expression not closed */ QSE_AWK_EENDSTR, /**< string or regular expression not closed */
QSE_AWK_EENDREX, /**< unexpected end of regular expression */ QSE_AWK_EENDREX, /**< unexpected end of regular expression */
QSE_AWK_ELBRACE, /**< left brace expected in place of '${0}' */ QSE_AWK_ELBRACE, /**< left brace expected in place of '${0}' */

View File

@ -1,5 +1,5 @@
/* /*
* $Id: map.h 205 2009-06-20 12:47:34Z hyunghwan.chung $ * $Id: map.h 248 2009-08-06 08:27:14Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
@ -360,21 +360,15 @@ qse_map_freeer_t qse_map_getfreeer (
qse_map_id_t id /* QSE_MAP_KEY or QSE_MAP_VAL */ qse_map_id_t id /* QSE_MAP_KEY or QSE_MAP_VAL */
); );
/****f* Common/qse_map_setfreeer /**
* NAME * The qse_map_setfreeer() function specifies how to destroy an element.
* qse_map_setfreeer - specify how to destroy an element * The @a freeer is called when a node containing the element is destroyed.
*
* DESCRIPTION
* The freeer is called when a node containing the element is destroyed.
*
* SYNOPSIS
*/ */
void qse_map_setfreeer ( void qse_map_setfreeer (
qse_map_t* map /* a map */, qse_map_t* map, /**< a map */
qse_map_id_t id /* QSE_MAP_KEY or QSE_MAP_VAL */, qse_map_id_t id, /**< QSE_MAP_KEY or QSE_MAP_VAL */
qse_map_freeer_t freeer /* an element freeer */ qse_map_freeer_t freeer /**< an element freeer */
); );
/******/
qse_map_hasher_t qse_map_gethasher ( qse_map_hasher_t qse_map_gethasher (
@ -414,75 +408,75 @@ void qse_map_setsizer (
qse_map_sizer_t sizer qse_map_sizer_t sizer
); );
/****f* Common/qse_map_search /**
* NAME
* qse_map_search - find a pair with a matching key
* DESCRIPTION
* The qse_map_search() function searches a map to find a pair with a * The qse_map_search() function searches a map to find a pair with a
* matching key. It returns the pointer to the pair found. If it fails * matching key. It returns the pointer to the pair found. If it fails
* to find one, it returns QSE_NULL. * to find one, it returns QSE_NULL.
* RETURN * @return pointer to the pair with a maching key,
* The qse_map_search() function returns the pointer to the pair with a * or QSE_NULL if no match is found.
* maching key, and QSE_NULL if no match is found.
* SYNOPSIS
*/ */
qse_map_pair_t* qse_map_search ( qse_map_pair_t* qse_map_search (
qse_map_t* map /* a map */, qse_map_t* map, /**< a map */
const void* kptr /* the pointer to a key */, const void* kptr, /**< the pointer to a key */
qse_size_t klen /* the size of the key in bytes */ qse_size_t klen /**< the size of the key */
); );
/******/
/****f* Common/qse_map_upsert /**
* NAME
* qse_map_upsert - update an existing pair or inesrt a new pair
* DESCRIPTION
* The qse_map_upsert() function searches a map for the pair with a matching * The qse_map_upsert() function searches a map for the pair with a matching
* key. If one is found, it updates the pair. Otherwise, it inserts a new * key. If one is found, it updates the pair. Otherwise, it inserts a new
* pair with a key and a value. It returns the pointer to the pair updated * pair with a key and a value. It returns the pointer to the pair updated
* or inserted. * or inserted.
* RETURN * @return a pointer to the updated or inserted pair on success,
* The qse_map_upsert() function returns a pointer to the updated or inserted * QSE_NULL on failure.
* pair on success, and QSE_NULL on failure.
* SYNOPSIS * SYNOPSIS
*/ */
qse_map_pair_t* qse_map_upsert ( qse_map_pair_t* qse_map_upsert (
qse_map_t* map /* a map */, qse_map_t* map, /**< a map */
void* kptr /* the pointer to a key */, void* kptr, /**< the pointer to a key */
qse_size_t klen /* the length of the key in bytes */, qse_size_t klen, /**< the length of the key */
void* vptr /* the pointer to a value */, void* vptr, /**< the pointer to a value */
qse_size_t vlen /* the length of the value in bytes */ qse_size_t vlen /**< the length of the value */
); );
/******/
/****f* Common/qse_map_insert /**
* NAME * The qse_map_ensert() function inserts a new pair with the key and the value
* qse_map_insert - insert a new pair with a key and a value * given. If there exists a pair with the key given, the function returns
* DESCRIPTION * the pair containing the key.
* @return pointer to a pair on success, QSE_NULL on failure.
*/
qse_map_pair_t* qse_map_ensert (
qse_map_t* map, /**< a map */
void* kptr, /**< the pointer to a key */
qse_size_t klen, /**< the length of the key */
void* vptr, /**< the pointer to a value */
qse_size_t vlen /**< the length of the value */
);
/**
* The qse_map_insert() function inserts a new pair with the key and the value * The qse_map_insert() function inserts a new pair with the key and the value
* given. If there exists a pair with the key given, the function returns * given. If there exists a pair with the key given, the function returns
* QSE_NULL without channging the value. * QSE_NULL without channging the value.
* RETURN * @return pointer to the pair created on success, QSE_NULL on failure.
* The qse_map_insert() function returns a pointer to the pair created on
* success, and QSE_NULL on failure.
* SYNOPSIS
*/ */
qse_map_pair_t* qse_map_insert ( qse_map_pair_t* qse_map_insert (
qse_map_t* map /* a map */, qse_map_t* map, /**< a map */
void* kptr /* the pointer to a key */, void* kptr, /**< the pointer to a key */
qse_size_t klen /* the length of the key in bytes */, qse_size_t klen, /**< the length of the key */
void* vptr /* the pointer to a value */, void* vptr, /**< the pointer to a value */
qse_size_t vlen /* the length of the value in bytes */ qse_size_t vlen /**< the length of the value */
); );
/******/
/* update the value of a existing pair with a matching key */ /**
* The qse_map_update() function updates the value of an existing pair
* with a matching key.
* @return pointer to the pair on success, QSE_NULL on no matching pair
*/
qse_map_pair_t* qse_map_update ( qse_map_pair_t* qse_map_update (
qse_map_t* map /* a map */, qse_map_t* map, /**< a map */
void* kptr /* the pointer to a key */, void* kptr, /**< the pointer to a key */
qse_size_t klen /* the length of the key in bytes */, qse_size_t klen, /**< the length of the key */
void* vptr /* the pointer to a value */, void* vptr, /**< the pointer to a value */
qse_size_t vlen /* the length of the value in bytes */ qse_size_t vlen /**< the length of the value */
); );
/* delete a pair with a matching key */ /* delete a pair with a matching key */

View File

@ -1,5 +1,5 @@
/* /*
* $Id: awk.c 247 2009-07-31 13:01:04Z hyunghwan.chung $ * $Id: awk.c 248 2009-08-06 08:27:14Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
@ -51,9 +51,10 @@ static int init_token (qse_mmgr_t* mmgr, qse_awk_token_t* token)
token->name = qse_str_open (mmgr, 0, 128); token->name = qse_str_open (mmgr, 0, 128);
if (token->name == QSE_NULL) return -1; if (token->name == QSE_NULL) return -1;
token->file = QSE_NULL;
token->type = 0; token->type = 0;
token->line = 0; token->lin = 0;
token->column = 0; token->col = 0;
return 0; return 0;
} }
@ -70,9 +71,10 @@ static void fini_token (qse_awk_token_t* token)
static void clear_token (qse_awk_token_t* token) static void clear_token (qse_awk_token_t* token)
{ {
if (token->name != QSE_NULL) qse_str_clear (token->name); if (token->name != QSE_NULL) qse_str_clear (token->name);
token->file = QSE_NULL;
token->type = 0; token->type = 0;
token->line = 0; token->lin = 0;
token->column = 0; token->col = 0;
} }
qse_awk_t* qse_awk_open (qse_mmgr_t* mmgr, qse_size_t xtn, qse_awk_prm_t* prm) qse_awk_t* qse_awk_open (qse_mmgr_t* mmgr, qse_size_t xtn, qse_awk_prm_t* prm)
@ -132,6 +134,13 @@ qse_awk_t* qse_awk_open (qse_mmgr_t* mmgr, qse_size_t xtn, qse_awk_prm_t* prm)
qse_map_setscale (awk->rwtab, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t)); qse_map_setscale (awk->rwtab, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t));
qse_map_setscale (awk->rwtab, QSE_MAP_VAL, QSE_SIZEOF(qse_char_t)); qse_map_setscale (awk->rwtab, QSE_MAP_VAL, QSE_SIZEOF(qse_char_t));
awk->sio.names = qse_map_open (mmgr, QSE_SIZEOF(awk), 128, 70);
if (awk->sio.names == QSE_NULL) goto oops;
*(qse_awk_t**)QSE_XTN(awk->sio.names) = awk;
qse_map_setcopier (awk->sio.names, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE);
qse_map_setscale (awk->sio.names, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t));
awk->sio.inp = &awk->sio.arg;
/* TODO: initial map size?? */ /* TODO: initial map size?? */
awk->tree.funs = qse_map_open (mmgr, QSE_SIZEOF(awk), 512, 70); awk->tree.funs = qse_map_open (mmgr, QSE_SIZEOF(awk), 512, 70);
if (awk->tree.funs == QSE_NULL) goto oops; if (awk->tree.funs == QSE_NULL) goto oops;
@ -150,9 +159,12 @@ qse_awk_t* qse_awk_open (qse_mmgr_t* mmgr, qse_size_t xtn, qse_awk_prm_t* prm)
awk->parse.named = qse_map_open (mmgr, QSE_SIZEOF(awk), 256, 70); awk->parse.named = qse_map_open (mmgr, QSE_SIZEOF(awk), 256, 70);
if (awk->parse.named == QSE_NULL) goto oops; if (awk->parse.named == QSE_NULL) goto oops;
*(qse_awk_t**)QSE_XTN(awk->parse.named) = awk; *(qse_awk_t**)QSE_XTN(awk->parse.named) = awk;
qse_map_setcopier (awk->parse.named, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE); qse_map_setcopier (
qse_map_setcopier (awk->parse.named, QSE_MAP_VAL, QSE_MAP_COPIER_INLINE); awk->parse.named, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE);
qse_map_setscale (awk->parse.named, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t)); qse_map_setcopier (
awk->parse.named, QSE_MAP_VAL, QSE_MAP_COPIER_INLINE);
qse_map_setscale (
awk->parse.named, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t));
awk->parse.gbls = qse_lda_open (mmgr, QSE_SIZEOF(awk), 128); awk->parse.gbls = qse_lda_open (mmgr, QSE_SIZEOF(awk), 128);
awk->parse.lcls = qse_lda_open (mmgr, QSE_SIZEOF(awk), 64); awk->parse.lcls = qse_lda_open (mmgr, QSE_SIZEOF(awk), 64);
@ -174,9 +186,6 @@ qse_awk_t* qse_awk_open (qse_mmgr_t* mmgr, qse_size_t xtn, qse_awk_prm_t* prm)
qse_lda_setcopier (awk->parse.params, QSE_LDA_COPIER_INLINE); qse_lda_setcopier (awk->parse.params, QSE_LDA_COPIER_INLINE);
qse_lda_setscale (awk->parse.params, QSE_SIZEOF(qse_char_t)); qse_lda_setscale (awk->parse.params, QSE_SIZEOF(qse_char_t));
awk->parse.nlcls_max = 0;
awk->sio.inp = &awk->sio.arg;
awk->option = QSE_AWK_CLASSIC; awk->option = QSE_AWK_CLASSIC;
awk->errinf.num = QSE_AWK_ENOERR; awk->errinf.num = QSE_AWK_ENOERR;
awk->errinf.lin = 0; awk->errinf.lin = 0;
@ -213,6 +222,7 @@ oops:
if (awk->parse.named) qse_map_close (awk->parse.named); if (awk->parse.named) qse_map_close (awk->parse.named);
if (awk->parse.funs) qse_map_close (awk->parse.funs); if (awk->parse.funs) qse_map_close (awk->parse.funs);
if (awk->tree.funs) qse_map_close (awk->tree.funs); if (awk->tree.funs) qse_map_close (awk->tree.funs);
if (awk->sio.names) qse_map_close (awk->sio.names);
if (awk->rwtab) qse_map_close (awk->rwtab); if (awk->rwtab) qse_map_close (awk->rwtab);
if (awk->wtab) qse_map_close (awk->wtab); if (awk->wtab) qse_map_close (awk->wtab);
fini_token (&awk->ntoken); fini_token (&awk->ntoken);
@ -236,6 +246,8 @@ int qse_awk_close (qse_awk_t* awk)
qse_map_close (awk->parse.funs); qse_map_close (awk->parse.funs);
qse_map_close (awk->tree.funs); qse_map_close (awk->tree.funs);
qse_map_close (awk->sio.names);
qse_map_close (awk->rwtab); qse_map_close (awk->rwtab);
qse_map_close (awk->wtab); qse_map_close (awk->wtab);
@ -253,15 +265,6 @@ int qse_awk_clear (qse_awk_t* awk)
{ {
awk->stopall = QSE_FALSE; awk->stopall = QSE_FALSE;
awk->sio.lex.curc = QSE_CHAR_EOF;
awk->sio.lex.ungotc_count = 0;
awk->sio.lex.line = 1;
awk->sio.lex.column = 1;
awk->sio.arg.b.pos = 0;
awk->sio.arg.b.len = 0;
QSE_ASSERT (awk->sio.inp == &awk->sio.arg);
clear_token (&awk->token); clear_token (&awk->token);
clear_token (&awk->ntoken); clear_token (&awk->ntoken);
clear_token (&awk->ptoken); clear_token (&awk->ptoken);
@ -323,6 +326,20 @@ int qse_awk_clear (qse_awk_t* awk)
awk->tree.chain_tail = QSE_NULL; awk->tree.chain_tail = QSE_NULL;
awk->tree.chain_size = 0; awk->tree.chain_size = 0;
QSE_ASSERT (awk->sio.inp == &awk->sio.arg);
qse_map_clear (awk->sio.names);
awk->sio.last.c = QSE_CHAR_EOF;
awk->sio.last.lin = 0;
awk->sio.last.col = 0;
awk->sio.last.file = QSE_NULL;
awk->sio.nungots = 0;
awk->sio.arg.lin = 1;
awk->sio.arg.col = 1;
awk->sio.arg.b.pos = 0;
awk->sio.arg.b.len = 0;
return 0; return 0;
} }
@ -429,3 +446,51 @@ int qse_awk_setword (
return 0; return 0;
} }
qse_size_t qse_awk_getmaxdepth (qse_awk_t* awk, int type)
{
return (type == QSE_AWK_DEPTH_BLOCK_PARSE)? awk->parse.depth.max.block:
(type == QSE_AWK_DEPTH_BLOCK_RUN)? awk->run.depth.max.block:
(type == QSE_AWK_DEPTH_EXPR_PARSE)? awk->parse.depth.max.expr:
(type == QSE_AWK_DEPTH_EXPR_RUN)? awk->run.depth.max.expr:
(type == QSE_AWK_DEPTH_REX_BUILD)? awk->rex.depth.max.build:
(type == QSE_AWK_DEPTH_REX_MATCH)? awk->rex.depth.max.match:
(type == QSE_AWK_DEPTH_INCLUDE)? awk->parse.depth.max.incl: 0;
}
void qse_awk_setmaxdepth (qse_awk_t* awk, int types, qse_size_t depth)
{
if (types & QSE_AWK_DEPTH_BLOCK_PARSE)
{
awk->parse.depth.max.block = depth;
}
if (types & QSE_AWK_DEPTH_EXPR_PARSE)
{
awk->parse.depth.max.expr = depth;
}
if (types & QSE_AWK_DEPTH_BLOCK_RUN)
{
awk->run.depth.max.block = depth;
}
if (types & QSE_AWK_DEPTH_EXPR_RUN)
{
awk->run.depth.max.expr = depth;
}
if (types & QSE_AWK_DEPTH_REX_BUILD)
{
awk->rex.depth.max.build = depth;
}
if (types & QSE_AWK_DEPTH_REX_MATCH)
{
awk->rex.depth.max.match = depth;
}
if (types & QSE_AWK_DEPTH_INCLUDE)
{
awk->parse.depth.max.incl = depth;
}
}

View File

@ -1,5 +1,5 @@
/* /*
* $Id: awk.h 247 2009-07-31 13:01:04Z hyunghwan.chung $ * $Id: awk.h 248 2009-08-06 08:27:14Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
@ -101,8 +101,18 @@ struct qse_awk_token_t
{ {
int type; int type;
qse_str_t* name; qse_str_t* name;
qse_size_t line; const qse_char_t* file;
qse_size_t column; qse_size_t lin;
qse_size_t col;
};
typedef struct qse_awk_lxc_t qse_awk_lxc_t;
struct qse_awk_lxc_t
{
qse_cint_t c;
qse_size_t lin;
qse_size_t col;
const qse_char_t* file;
}; };
struct qse_awk_t struct qse_awk_t
@ -168,10 +178,6 @@ struct qse_awk_t
/* maximum number of local variables */ /* maximum number of local variables */
qse_size_t nlcls_max; qse_size_t nlcls_max;
qse_awk_nde_t* (*parse_block) (
qse_awk_t*,qse_size_t,qse_bool_t);
} parse; } parse;
/* source code management */ /* source code management */
@ -180,20 +186,14 @@ struct qse_awk_t
qse_awk_sio_fun_t inf; qse_awk_sio_fun_t inf;
qse_awk_sio_fun_t outf; qse_awk_sio_fun_t outf;
struct qse_awk_lxc_t last;
{
qse_cint_t curc;
qse_cint_t ungotc[5];
qse_size_t ungotc_line[5];
qse_size_t ungotc_column[5];
qse_size_t ungotc_count;
qse_size_t line; qse_size_t nungots;
qse_size_t column; qse_awk_lxc_t ungot[5];
} lex;
qse_awk_sio_arg_t arg; qse_awk_sio_arg_t arg; /* for the top level source */
qse_awk_sio_arg_t* inp; /* current input */ qse_awk_sio_arg_t* inp; /* current input */
qse_map_t* names;
} sio; } sio;
/* previous token */ /* previous token */

View File

@ -1,5 +1,5 @@
/* /*
* $Id: err.c 247 2009-07-31 13:01:04Z hyunghwan.chung $ * $Id: err.c 248 2009-08-06 08:27:14Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
@ -45,7 +45,6 @@ const qse_char_t* qse_awk_dflerrstr (qse_awk_t* awk, qse_awk_errnum_t errnum)
QSE_T("invalid character '${0}'"), QSE_T("invalid character '${0}'"),
QSE_T("invalid digit '${0}'"), QSE_T("invalid digit '${0}'"),
QSE_T("failed to unget character"),
QSE_T("unexpected end of source"), QSE_T("unexpected end of source"),
QSE_T("comment not closed properly"), QSE_T("comment not closed properly"),

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* /*
* $Id: map.c 120 2009-04-10 05:00:00Z hyunghwan.chung $ * $Id: map.c 248 2009-08-06 08:27:14Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
@ -46,6 +46,11 @@ QSE_IMPLEMENT_COMMON_FUNCTIONS (map)
#define KTOB(map,len) ((len)*(map)->scale[QSE_MAP_KEY]) #define KTOB(map,len) ((len)*(map)->scale[QSE_MAP_KEY])
#define VTOB(map,len) ((len)*(map)->scale[QSE_MAP_VAL]) #define VTOB(map,len) ((len)*(map)->scale[QSE_MAP_VAL])
#define UPSERT 1
#define UPDATE 2
#define ENSERT 3
#define INSERT 4
static int reorganize (map_t* map); static int reorganize (map_t* map);
static size_t hash_key (map_t* map, const void* kptr, size_t klen) static size_t hash_key (map_t* map, const void* kptr, size_t klen)
@ -411,8 +416,8 @@ pair_t* qse_map_search (map_t* map, const void* kptr, size_t klen)
return QSE_NULL; return QSE_NULL;
} }
pair_t* qse_map_upsert ( static pair_t* insert (
map_t* map, void* kptr, size_t klen, void* vptr, size_t vlen) map_t* map, void* kptr, size_t klen, void* vptr, size_t vlen, int opt)
{ {
pair_t* pair, * p, * prev, * next; pair_t* pair, * p, * prev, * next;
size_t hc; size_t hc;
@ -427,23 +432,44 @@ pair_t* qse_map_upsert (
if (map->comper (map, KPTR(pair), KLEN(pair), kptr, klen) == 0) if (map->comper (map, KPTR(pair), KLEN(pair), kptr, klen) == 0)
{ {
/* found a pair with a matching key */
switch (opt)
{
case UPSERT:
case UPDATE:
p = change_pair_val (map, pair, vptr, vlen); p = change_pair_val (map, pair, vptr, vlen);
if (p == QSE_NULL) return QSE_NULL; /* change error */ if (p == QSE_NULL)
{
/* error in change the value */
return QSE_NULL;
}
if (p != pair) if (p != pair)
{ {
/* the pair has been reallocated. relink it */ /* pair reallocated.
if (prev == QSE_NULL) map->bucket[hc] = p; * relink it */
if (prev == QSE_NULL)
map->bucket[hc] = p;
else NEXT(prev) = p; else NEXT(prev) = p;
NEXT(p) = next; NEXT(p) = next;
} }
return p;
return p; /* value changed for the existing key */ case ENSERT:
/* return existing pair */
return pair;
case INSERT:
/* return failure */
return QSE_NULL;
}
} }
prev = pair; prev = pair;
pair = next; pair = next;
} }
if (opt == UPDATE) return QSE_NULL;
if (map->threshold > 0 && map->size >= map->threshold) if (map->threshold > 0 && map->size >= map->threshold)
{ {
if (reorganize(map) == 0) /* ignore the error */ if (reorganize(map) == 0) /* ignore the error */
@ -464,78 +490,29 @@ pair_t* qse_map_upsert (
return pair; /* new key added */ return pair; /* new key added */
} }
pair_t* qse_map_insert (map_t* map, void* kptr, size_t klen, void* vptr, size_t vlen) pair_t* qse_map_upsert (
map_t* map, void* kptr, size_t klen, void* vptr, size_t vlen)
{ {
pair_t* pair; return insert (map, kptr, klen, vptr, vlen, UPSERT);
size_t hc;
hc = map->hasher(map,kptr,klen) % map->capa;
pair = map->bucket[hc];
while (pair != QSE_NULL)
{
if (map->comper (map, KPTR(pair), KLEN(pair), kptr, klen) == 0)
{
return QSE_NULL;
}
pair = NEXT(pair);
}
if (map->threshold > 0 && map->size >= map->threshold)
{
if (reorganize(map) == 0) /* ignore the error */
{
hc = map->hasher(map,kptr,klen) % map->capa;
}
}
QSE_ASSERT (pair == QSE_NULL);
pair = alloc_pair (map, kptr, klen, vptr, vlen);
if (pair == QSE_NULL) return QSE_NULL;
NEXT(pair) = map->bucket[hc];
map->bucket[hc] = pair;
map->size++;
return pair;
} }
pair_t* qse_map_update (map_t* map, void* kptr, size_t klen, void* vptr, size_t vlen) pair_t* qse_map_ensert (
map_t* map, void* kptr, size_t klen, void* vptr, size_t vlen)
{ {
pair_t* pair, * p, * prev, * next; return insert (map, kptr, klen, vptr, vlen, ENSERT);
size_t hc; }
hc = map->hasher(map,kptr,klen) % map->capa; pair_t* qse_map_insert (
pair = map->bucket[hc]; map_t* map, void* kptr, size_t klen, void* vptr, size_t vlen)
prev = QSE_NULL; {
return insert (map, kptr, klen, vptr, vlen, INSERT);
}
while (pair != QSE_NULL)
{
next = NEXT(pair);
if (map->comper (map, KPTR(pair), KLEN(pair), kptr, klen) == 0) pair_t* qse_map_update (
{ map_t* map, void* kptr, size_t klen, void* vptr, size_t vlen)
p = change_pair_val (map, pair, vptr, vlen); {
return insert (map, kptr, klen, vptr, vlen, UPDATE);
if (p == QSE_NULL) return QSE_NULL; /* change error */
if (p != pair)
{
/* the pair has been reallocated. relink it */
if (prev == QSE_NULL) map->bucket[hc] = p;
else NEXT(prev) = p;
NEXT(p) = next;
}
return p; /* value changed for the existing key */
}
prev = pair;
pair = next;
}
return QSE_NULL;
} }
int qse_map_delete (map_t* map, const void* kptr, size_t klen) int qse_map_delete (map_t* map, const void* kptr, size_t klen)

View File

@ -1,4 +1,8 @@
# cannot use function name as a parameter name # cannot use function name as a parameter name
# unless QSE_AWK_STRICTNAMING is off # unless QSE_AWK_STRICTNAMING is off
function f(f) { print f; } function f(f) { print f; }
/*
* the begin block
*/
BEGIN { f("hello"); } BEGIN { f("hello"); }

View File

@ -956,7 +956,7 @@ BEGIN {
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
../../cmd/awk/qseawk --newline=on -o- -f lang-004.awk </dev/stdin 2>&1 ../../cmd/awk/qseawk --newline=on -o- -f lang-004.awk </dev/stdin 2>&1
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
ERROR: CODE [44] LINE [3] function 'a' redefined ERROR: CODE [43] LINE [3] function 'a' redefined
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
../../cmd/awk/qseawk --implicit=off --explicit=on --newline=on -o- -f lang-005.awk </dev/stdin 2>&1 ../../cmd/awk/qseawk --implicit=off --explicit=on --newline=on -o- -f lang-005.awk </dev/stdin 2>&1
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -984,7 +984,7 @@ BEGIN {
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
../../cmd/awk/qseawk --implicit=off --explicit=on --newline=on -o- -f lang-006.awk </dev/stdin 2>&1 ../../cmd/awk/qseawk --implicit=off --explicit=on --newline=on -o- -f lang-006.awk </dev/stdin 2>&1
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
ERROR: CODE [45] LINE [5] global variable 'a' redefined ERROR: CODE [44] LINE [5] global variable 'a' redefined
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
../../cmd/awk/qseawk --implicit=on --explicit=on --newline=on -o- -f lang-007.awk </dev/stdin 2>&1 ../../cmd/awk/qseawk --implicit=on --explicit=on --newline=on -o- -f lang-007.awk </dev/stdin 2>&1
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -1352,7 +1352,7 @@ BEGIN {
printf ("%s\n",10.34); printf ("%s\n",10.34);
} }
ERROR: CODE [105] LINE [3] recursion detected in format conversion ERROR: CODE [104] LINE [3] recursion detected in format conversion
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
../../cmd/awk/qseawk --newline=on -o- -f lang-014.awk </dev/stdin 2>&1 ../../cmd/awk/qseawk --newline=on -o- -f lang-014.awk </dev/stdin 2>&1
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -1481,27 +1481,27 @@ END {
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
../../cmd/awk/qseawk --explicit=on --newline=on -o- -f lang-018.awk </dev/stdin 2>&1 ../../cmd/awk/qseawk --explicit=on --newline=on -o- -f lang-018.awk </dev/stdin 2>&1
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
ERROR: CODE [49] LINE [1] duplicate global variable 'ARGV' ERROR: CODE [48] LINE [1] duplicate global variable 'ARGV'
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
../../cmd/awk/qseawk --explicit=on --newline=on -o- -f lang-019.awk </dev/stdin 2>&1 ../../cmd/awk/qseawk --explicit=on --newline=on -o- -f lang-019.awk </dev/stdin 2>&1
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
ERROR: CODE [51] LINE [1] '+' not a valid parameter name ERROR: CODE [50] LINE [1] '+' not a valid parameter name
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
../../cmd/awk/qseawk --explicit=on --newline=on -o- -f lang-020.awk </dev/stdin 2>&1 ../../cmd/awk/qseawk --explicit=on --newline=on -o- -f lang-020.awk </dev/stdin 2>&1
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
ERROR: CODE [52] LINE [1] '+' not a valid variable name ERROR: CODE [51] LINE [1] '+' not a valid variable name
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
../../cmd/awk/qseawk --explicit=on --newline=on -o- -f lang-021.awk </dev/stdin 2>&1 ../../cmd/awk/qseawk --explicit=on --newline=on -o- -f lang-021.awk </dev/stdin 2>&1
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
ERROR: CODE [52] LINE [3] '+' not a valid variable name ERROR: CODE [51] LINE [3] '+' not a valid variable name
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
../../cmd/awk/qseawk --newline=on -o- -f lang-022.awk </dev/stdin 2>&1 ../../cmd/awk/qseawk --newline=on -o- -f lang-022.awk </dev/stdin 2>&1
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
ERROR: CODE [25] LINE [2] left parenthesis expected in place of '=' ERROR: CODE [24] LINE [2] left parenthesis expected in place of '='
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
../../cmd/awk/qseawk --explicit=on --newline=on -o- -f lang-023.awk </dev/stdin 2>&1 ../../cmd/awk/qseawk --explicit=on --newline=on -o- -f lang-023.awk </dev/stdin 2>&1
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
ERROR: CODE [30] LINE [5] colon expected in place of ';' ERROR: CODE [29] LINE [5] colon expected in place of ';'
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
../../cmd/awk/qseawk --explicit=on --newline=on -o- -f lang-024.awk </dev/stdin 2>&1 ../../cmd/awk/qseawk --explicit=on --newline=on -o- -f lang-024.awk </dev/stdin 2>&1
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -1520,7 +1520,7 @@ BEGIN {
delete iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiix; delete iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiix;
} }
ERROR: CODE [80] LINE [3] variable 'iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiix' not deletable ERROR: CODE [79] LINE [3] variable 'iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiix' not deletable
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
../../cmd/awk/qseawk --newline=on -o- -f lang-026.awk </dev/stdin 2>&1 ../../cmd/awk/qseawk --newline=on -o- -f lang-026.awk </dev/stdin 2>&1
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -1532,7 +1532,7 @@ BEGIN {
} }
abc abc
ERROR: CODE [88] LINE [4] map 'abc' not assignable with a scalar ERROR: CODE [87] LINE [4] map 'abc' not assignable with a scalar
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
../../cmd/awk/qseawk --newline=on -o- -f lang-027.awk </dev/stdin 2>&1 ../../cmd/awk/qseawk --newline=on -o- -f lang-027.awk </dev/stdin 2>&1
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -1540,11 +1540,11 @@ ERROR: CODE [17] LINE [2] invalid character '<NUL>'
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
../../cmd/awk/qseawk --newline=on -o- -f lang-028.awk </dev/stdin 2>&1 ../../cmd/awk/qseawk --newline=on -o- -f lang-028.awk </dev/stdin 2>&1
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
ERROR: CODE [43] LINE [2] intrinsic function 'substr' redefined ERROR: CODE [42] LINE [2] intrinsic function 'substr' redefined
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
../../cmd/awk/qseawk --explicit=on --newline=on -o- -f lang-029.awk </dev/stdin 2>&1 ../../cmd/awk/qseawk --explicit=on --newline=on -o- -f lang-029.awk </dev/stdin 2>&1
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
ERROR: CODE [44] LINE [9] function 'abc' redefined ERROR: CODE [43] LINE [9] function 'abc' redefined
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
../../cmd/awk/qseawk --newline=on -o- -f lang-030.awk </dev/stdin 2>&1 ../../cmd/awk/qseawk --newline=on -o- -f lang-030.awk </dev/stdin 2>&1
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------