enhanced the awk parser
This commit is contained in:
parent
ff92573543
commit
3fc663609e
@ -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.
|
||||
|
||||
@ -92,9 +92,8 @@ public:
|
||||
ERR_EXPRNST = QSE_AWK_EEXPRNST,
|
||||
ERR_LXCHR = QSE_AWK_ELXCHR,
|
||||
ERR_LXDIG = QSE_AWK_ELXDIG,
|
||||
ERR_LXUNG = QSE_AWK_ELXUNG,
|
||||
ERR_ENDSRC = QSE_AWK_EENDSRC,
|
||||
ERR_ENDCMT = QSE_AWK_EENDCMT,
|
||||
ERR_ECMNTNC = QSE_AWK_ECMNTNC,
|
||||
ERR_ENDSTR = QSE_AWK_EENDSTR,
|
||||
ERR_ENDREX = QSE_AWK_EENDREX,
|
||||
ERR_LBRACE = QSE_AWK_ELBRACE,
|
||||
|
@ -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.
|
||||
|
||||
@ -273,7 +273,7 @@ typedef enum qse_awk_sio_cmd_t qse_awk_sio_cmd_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 */
|
||||
|
||||
/*-- from here down, internal use only --*/
|
||||
@ -284,12 +284,8 @@ struct qse_awk_sio_arg_t
|
||||
qse_size_t len;
|
||||
} b;
|
||||
|
||||
struct
|
||||
{
|
||||
qse_size_t line;
|
||||
qse_size_t column;
|
||||
} saved;
|
||||
|
||||
qse_size_t lin;
|
||||
qse_size_t col;
|
||||
struct qse_awk_sio_arg_t* next;
|
||||
};
|
||||
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_ELXDIG, /**< invalid digit '${0}' */
|
||||
QSE_AWK_ELXUNG, /**< failed to unget character */
|
||||
|
||||
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_EENDREX, /**< unexpected end of regular expression */
|
||||
QSE_AWK_ELBRACE, /**< left brace expected in place of '${0}' */
|
||||
|
@ -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.
|
||||
|
||||
@ -360,21 +360,15 @@ qse_map_freeer_t qse_map_getfreeer (
|
||||
qse_map_id_t id /* QSE_MAP_KEY or QSE_MAP_VAL */
|
||||
);
|
||||
|
||||
/****f* Common/qse_map_setfreeer
|
||||
* NAME
|
||||
* qse_map_setfreeer - specify how to destroy an element
|
||||
*
|
||||
* DESCRIPTION
|
||||
* The freeer is called when a node containing the element is destroyed.
|
||||
*
|
||||
* SYNOPSIS
|
||||
/**
|
||||
* The qse_map_setfreeer() function specifies how to destroy an element.
|
||||
* The @a freeer is called when a node containing the element is destroyed.
|
||||
*/
|
||||
void qse_map_setfreeer (
|
||||
qse_map_t* map /* a map */,
|
||||
qse_map_id_t id /* QSE_MAP_KEY or QSE_MAP_VAL */,
|
||||
qse_map_freeer_t freeer /* an element freeer */
|
||||
qse_map_t* map, /**< a map */
|
||||
qse_map_id_t id, /**< QSE_MAP_KEY or QSE_MAP_VAL */
|
||||
qse_map_freeer_t freeer /**< an element freeer */
|
||||
);
|
||||
/******/
|
||||
|
||||
|
||||
qse_map_hasher_t qse_map_gethasher (
|
||||
@ -414,75 +408,75 @@ void qse_map_setsizer (
|
||||
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
|
||||
* matching key. It returns the pointer to the pair found. If it fails
|
||||
* to find one, it returns QSE_NULL.
|
||||
* RETURN
|
||||
* The qse_map_search() function returns the pointer to the pair with a
|
||||
* maching key, and QSE_NULL if no match is found.
|
||||
* SYNOPSIS
|
||||
* @return pointer to the pair with a maching key,
|
||||
* or QSE_NULL if no match is found.
|
||||
*/
|
||||
qse_map_pair_t* qse_map_search (
|
||||
qse_map_t* map /* a map */,
|
||||
const void* kptr /* the pointer to a key */,
|
||||
qse_size_t klen /* the size of the key in bytes */
|
||||
qse_map_t* map, /**< a map */
|
||||
const void* kptr, /**< the pointer to a key */
|
||||
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
|
||||
* 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
|
||||
* or inserted.
|
||||
* RETURN
|
||||
* The qse_map_upsert() function returns a pointer to the updated or inserted
|
||||
* pair on success, and QSE_NULL on failure.
|
||||
* @return a pointer to the updated or inserted pair on success,
|
||||
* QSE_NULL on failure.
|
||||
* SYNOPSIS
|
||||
*/
|
||||
qse_map_pair_t* qse_map_upsert (
|
||||
qse_map_t* map /* a map */,
|
||||
void* kptr /* the pointer to a key */,
|
||||
qse_size_t klen /* the length of the key in bytes */,
|
||||
void* vptr /* the pointer to a value */,
|
||||
qse_size_t vlen /* the length of the value in bytes */
|
||||
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 */
|
||||
);
|
||||
/******/
|
||||
|
||||
/****f* Common/qse_map_insert
|
||||
* NAME
|
||||
* qse_map_insert - insert a new pair with a key and a value
|
||||
* DESCRIPTION
|
||||
/**
|
||||
* The qse_map_ensert() function inserts a new pair with the key and the value
|
||||
* given. If there exists a pair with the key given, the function returns
|
||||
* 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
|
||||
* given. If there exists a pair with the key given, the function returns
|
||||
* QSE_NULL without channging the value.
|
||||
* RETURN
|
||||
* The qse_map_insert() function returns a pointer to the pair created on
|
||||
* success, and QSE_NULL on failure.
|
||||
* SYNOPSIS
|
||||
* @return pointer to the pair created on success, QSE_NULL on failure.
|
||||
*/
|
||||
qse_map_pair_t* qse_map_insert (
|
||||
qse_map_t* map /* a map */,
|
||||
void* kptr /* the pointer to a key */,
|
||||
qse_size_t klen /* the length of the key in bytes */,
|
||||
void* vptr /* the pointer to a value */,
|
||||
qse_size_t vlen /* the length of the value in bytes */
|
||||
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 */
|
||||
);
|
||||
/******/
|
||||
|
||||
/* 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_t* map /* a map */,
|
||||
void* kptr /* the pointer to a key */,
|
||||
qse_size_t klen /* the length of the key in bytes */,
|
||||
void* vptr /* the pointer to a value */,
|
||||
qse_size_t vlen /* the length of the value in bytes */
|
||||
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 */
|
||||
);
|
||||
|
||||
/* delete a pair with a matching key */
|
||||
|
@ -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.
|
||||
|
||||
@ -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);
|
||||
if (token->name == QSE_NULL) return -1;
|
||||
|
||||
token->file = QSE_NULL;
|
||||
token->type = 0;
|
||||
token->line = 0;
|
||||
token->column = 0;
|
||||
token->lin = 0;
|
||||
token->col = 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)
|
||||
{
|
||||
if (token->name != QSE_NULL) qse_str_clear (token->name);
|
||||
token->file = QSE_NULL;
|
||||
token->type = 0;
|
||||
token->line = 0;
|
||||
token->column = 0;
|
||||
token->lin = 0;
|
||||
token->col = 0;
|
||||
}
|
||||
|
||||
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_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?? */
|
||||
awk->tree.funs = qse_map_open (mmgr, QSE_SIZEOF(awk), 512, 70);
|
||||
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);
|
||||
if (awk->parse.named == QSE_NULL) goto oops;
|
||||
*(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 (awk->parse.named, QSE_MAP_VAL, 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_KEY, QSE_MAP_COPIER_INLINE);
|
||||
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.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_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->errinf.num = QSE_AWK_ENOERR;
|
||||
awk->errinf.lin = 0;
|
||||
@ -213,6 +222,7 @@ oops:
|
||||
if (awk->parse.named) qse_map_close (awk->parse.named);
|
||||
if (awk->parse.funs) qse_map_close (awk->parse.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->wtab) qse_map_close (awk->wtab);
|
||||
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->tree.funs);
|
||||
qse_map_close (awk->sio.names);
|
||||
|
||||
qse_map_close (awk->rwtab);
|
||||
qse_map_close (awk->wtab);
|
||||
|
||||
@ -253,15 +265,6 @@ int qse_awk_clear (qse_awk_t* awk)
|
||||
{
|
||||
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->ntoken);
|
||||
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_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;
|
||||
}
|
||||
|
||||
@ -429,3 +446,51 @@ int qse_awk_setword (
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
||||
@ -101,8 +101,18 @@ struct qse_awk_token_t
|
||||
{
|
||||
int type;
|
||||
qse_str_t* name;
|
||||
qse_size_t line;
|
||||
qse_size_t column;
|
||||
const qse_char_t* file;
|
||||
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
|
||||
@ -168,10 +178,6 @@ struct qse_awk_t
|
||||
|
||||
/* maximum number of local variables */
|
||||
qse_size_t nlcls_max;
|
||||
|
||||
qse_awk_nde_t* (*parse_block) (
|
||||
qse_awk_t*,qse_size_t,qse_bool_t);
|
||||
|
||||
} parse;
|
||||
|
||||
/* source code management */
|
||||
@ -180,20 +186,14 @@ struct qse_awk_t
|
||||
qse_awk_sio_fun_t inf;
|
||||
qse_awk_sio_fun_t outf;
|
||||
|
||||
struct
|
||||
{
|
||||
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_awk_lxc_t last;
|
||||
|
||||
qse_size_t line;
|
||||
qse_size_t column;
|
||||
} lex;
|
||||
qse_size_t nungots;
|
||||
qse_awk_lxc_t ungot[5];
|
||||
|
||||
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_map_t* names;
|
||||
} sio;
|
||||
|
||||
/* previous token */
|
||||
|
@ -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.
|
||||
|
||||
@ -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 digit '${0}'"),
|
||||
QSE_T("failed to unget character"),
|
||||
|
||||
QSE_T("unexpected end of source"),
|
||||
QSE_T("comment not closed properly"),
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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.
|
||||
|
||||
@ -46,6 +46,11 @@ QSE_IMPLEMENT_COMMON_FUNCTIONS (map)
|
||||
#define KTOB(map,len) ((len)*(map)->scale[QSE_MAP_KEY])
|
||||
#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 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;
|
||||
}
|
||||
|
||||
pair_t* qse_map_upsert (
|
||||
map_t* map, void* kptr, size_t klen, void* vptr, size_t vlen)
|
||||
static pair_t* insert (
|
||||
map_t* map, void* kptr, size_t klen, void* vptr, size_t vlen, int opt)
|
||||
{
|
||||
pair_t* pair, * p, * prev, * next;
|
||||
size_t hc;
|
||||
@ -427,23 +432,44 @@ pair_t* qse_map_upsert (
|
||||
|
||||
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);
|
||||
if (p == QSE_NULL) return QSE_NULL; /* change error */
|
||||
if (p == QSE_NULL)
|
||||
{
|
||||
/* error in change the value */
|
||||
return QSE_NULL;
|
||||
}
|
||||
if (p != pair)
|
||||
{
|
||||
/* the pair has been reallocated. relink it */
|
||||
if (prev == QSE_NULL) map->bucket[hc] = p;
|
||||
/* pair reallocated.
|
||||
* relink it */
|
||||
if (prev == QSE_NULL)
|
||||
map->bucket[hc] = p;
|
||||
else NEXT(prev) = p;
|
||||
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;
|
||||
pair = next;
|
||||
}
|
||||
|
||||
if (opt == UPDATE) return QSE_NULL;
|
||||
|
||||
if (map->threshold > 0 && map->size >= map->threshold)
|
||||
{
|
||||
if (reorganize(map) == 0) /* ignore the error */
|
||||
@ -464,78 +490,29 @@ pair_t* qse_map_upsert (
|
||||
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;
|
||||
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;
|
||||
return insert (map, kptr, klen, vptr, vlen, UPSERT);
|
||||
}
|
||||
|
||||
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;
|
||||
size_t hc;
|
||||
return insert (map, kptr, klen, vptr, vlen, ENSERT);
|
||||
}
|
||||
|
||||
hc = map->hasher(map,kptr,klen) % map->capa;
|
||||
pair = map->bucket[hc];
|
||||
prev = QSE_NULL;
|
||||
pair_t* qse_map_insert (
|
||||
map_t* map, void* kptr, size_t klen, void* vptr, size_t vlen)
|
||||
{
|
||||
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)
|
||||
{
|
||||
p = change_pair_val (map, pair, vptr, vlen);
|
||||
|
||||
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;
|
||||
pair_t* qse_map_update (
|
||||
map_t* map, void* kptr, size_t klen, void* vptr, size_t vlen)
|
||||
{
|
||||
return insert (map, kptr, klen, vptr, vlen, UPDATE);
|
||||
}
|
||||
|
||||
int qse_map_delete (map_t* map, const void* kptr, size_t klen)
|
||||
|
@ -1,4 +1,8 @@
|
||||
# cannot use function name as a parameter name
|
||||
# unless QSE_AWK_STRICTNAMING is off
|
||||
function f(f) { print f; }
|
||||
|
||||
/*
|
||||
* the begin block
|
||||
*/
|
||||
BEGIN { f("hello"); }
|
||||
|
@ -956,7 +956,7 @@ BEGIN {
|
||||
--------------------------------------------------------------------------------
|
||||
../../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
|
||||
--------------------------------------------------------------------------------
|
||||
@ -984,7 +984,7 @@ BEGIN {
|
||||
--------------------------------------------------------------------------------
|
||||
../../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
|
||||
--------------------------------------------------------------------------------
|
||||
@ -1352,7 +1352,7 @@ BEGIN {
|
||||
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
|
||||
--------------------------------------------------------------------------------
|
||||
@ -1481,27 +1481,27 @@ END {
|
||||
--------------------------------------------------------------------------------
|
||||
../../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
|
||||
--------------------------------------------------------------------------------
|
||||
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
|
||||
--------------------------------------------------------------------------------
|
||||
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
|
||||
--------------------------------------------------------------------------------
|
||||
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
|
||||
--------------------------------------------------------------------------------
|
||||
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
|
||||
--------------------------------------------------------------------------------
|
||||
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
|
||||
--------------------------------------------------------------------------------
|
||||
@ -1520,7 +1520,7 @@ BEGIN {
|
||||
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
|
||||
--------------------------------------------------------------------------------
|
||||
@ -1532,7 +1532,7 @@ BEGIN {
|
||||
}
|
||||
|
||||
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
|
||||
--------------------------------------------------------------------------------
|
||||
@ -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
|
||||
--------------------------------------------------------------------------------
|
||||
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
|
||||
--------------------------------------------------------------------------------
|
||||
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
|
||||
--------------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user