From 40c5fef59c396276c7cc2b5a8a34fa513c22ed4d Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Thu, 3 Aug 2006 15:50:04 +0000 Subject: [PATCH] *** empty log message *** --- ase/awk/awk.h | 6 ++- ase/awk/awk_i.h | 4 +- ase/awk/err.c | 7 +++- ase/awk/parse.c | 98 +++++++++++++++++++++++++++----------------- ase/awk/run.c | 27 ++++++++++-- ase/test/awk/t25.awk | 2 +- ase/test/awk/t26.awk | 13 ++++++ 7 files changed, 110 insertions(+), 47 deletions(-) create mode 100644 ase/test/awk/t26.awk diff --git a/ase/awk/awk.h b/ase/awk/awk.h index f3e79813..516fbc74 100644 --- a/ase/awk/awk.h +++ b/ase/awk/awk.h @@ -1,5 +1,5 @@ /* - * $Id: awk.h,v 1.86 2006-08-03 09:53:42 bacon Exp $ + * $Id: awk.h,v 1.87 2006-08-03 15:49:37 bacon Exp $ */ #ifndef _XP_AWK_AWK_H_ @@ -146,6 +146,8 @@ enum XP_AWK_EWHILE, /* keyword 'while' is expected */ XP_AWK_EASSIGNMENT, /* assignment statement expected */ XP_AWK_EIDENT, /* identifier expected */ + XP_AWK_EBEGINBLOCK, /* BEGIN requires an action block */ + XP_AWK_EENDBLOCK, /* END requires an action block */ XP_AWK_EDUPBEGIN, /* duplicate BEGIN */ XP_AWK_EDUPEND, /* duplicate END */ XP_AWK_EDUPFUNC, /* duplicate function name */ @@ -175,6 +177,8 @@ enum XP_AWK_ENOTSCALARIZABLE, /* not scalarizable variable */ XP_AWK_EVALTYPE, /* wrong value type */ XP_AWK_EPIPE, /* pipe operation error */ + XP_AWK_ENEXTCALL, /* next called from BEGIN or END */ + XP_AWK_ENEXTFILECALL, /* nextfile called from BEGIN or END */ XP_AWK_EIOIMPL, /* wrong implementation of user io handler */ XP_AWK_EINTERNAL /* internal error */ }; diff --git a/ase/awk/awk_i.h b/ase/awk/awk_i.h index 492def48..7c1b8665 100644 --- a/ase/awk/awk_i.h +++ b/ase/awk/awk_i.h @@ -1,5 +1,5 @@ /* - * $Id: awk_i.h,v 1.37 2006-08-02 14:36:22 bacon Exp $ + * $Id: awk_i.h,v 1.38 2006-08-03 15:49:37 bacon Exp $ */ #ifndef _XP_AWK_AWKI_H_ @@ -177,6 +177,8 @@ struct xp_awk_run_t xp_size_t icache_count; xp_size_t rcache_count; + xp_awk_nde_blk_t* active_block; + struct { xp_char_t buf[1024]; diff --git a/ase/awk/err.c b/ase/awk/err.c index 2fd748db..3fcfb75f 100644 --- a/ase/awk/err.c +++ b/ase/awk/err.c @@ -1,5 +1,5 @@ /* - * $Id: err.c,v 1.30 2006-08-03 09:53:42 bacon Exp $ + * $Id: err.c,v 1.31 2006-08-03 15:49:37 bacon Exp $ */ #include @@ -64,6 +64,8 @@ const xp_char_t* xp_awk_geterrstr (xp_awk_t* awk) XP_T("keyword 'while' expected"), XP_T("assignment statement expected"), XP_T("identifier expected"), + XP_T("BEGIN requires an action block"), + XP_T("END requires an action block"), XP_T("duplicate BEGIN"), XP_T("duplicate END"), XP_T("duplicate function name"), @@ -92,8 +94,9 @@ const xp_char_t* xp_awk_geterrstr (xp_awk_t* awk) XP_T("variable not scalarizable"), XP_T("wrong value type"), XP_T("pipe operation error"), + XP_T("next cannot be called from the BEGIN or END block"), + XP_T("nextfile cannot be called from the BEGIN or END block"), XP_T("wrong implementation of user-defined io handler"), - XP_T("internal error that should never have happened") }; diff --git a/ase/awk/parse.c b/ase/awk/parse.c index 32c0bfa8..831fae3a 100644 --- a/ase/awk/parse.c +++ b/ase/awk/parse.c @@ -1,5 +1,5 @@ /* - * $Id: parse.c,v 1.154 2006-08-03 09:58:15 bacon Exp $ + * $Id: parse.c,v 1.155 2006-08-03 15:49:37 bacon Exp $ */ #include @@ -102,12 +102,14 @@ enum enum { - PARSE_BLOCK_GLOBAL, - PARSE_BLOCK_FUNCTION, - PARSE_BLOCK_BEGIN, - PARSE_BLOCK_END, - PARSE_BLOCK_PATTERN, - PARSE_BLOCK_ACTION + PARSE_GLOBAL, + PARSE_FUNCTION, + PARSE_BEGIN, + PARSE_END, + PARSE_BEGIN_BLOCK, + PARSE_END_BLOCK, + PARSE_PATTERN, + PARSE_ACTION_BLOCK }; enum @@ -139,7 +141,6 @@ static xp_awk_nde_t* __parse_end (xp_awk_t* awk); static xp_awk_chain_t* __parse_pattern_block ( xp_awk_t* awk, xp_awk_nde_t* ptn, xp_bool_t blockless); -static xp_awk_nde_t* __parse_action (xp_awk_t* awk); static xp_awk_nde_t* __parse_block (xp_awk_t* awk, xp_bool_t is_top); static xp_awk_nde_t* __parse_statement (xp_awk_t* awk); static xp_awk_nde_t* __parse_statement_nb (xp_awk_t* awk); @@ -456,7 +457,7 @@ static xp_awk_t* __parse_progunit (xp_awk_t* awk) { xp_size_t nglobals; - awk->parse.id.block = PARSE_BLOCK_GLOBAL; + awk->parse.id.block = PARSE_GLOBAL; if (__get_token(awk) == -1) return XP_NULL; @@ -471,23 +472,49 @@ static xp_awk_t* __parse_progunit (xp_awk_t* awk) } else if (MATCH(awk,TOKEN_FUNCTION)) { - awk->parse.id.block = PARSE_BLOCK_FUNCTION; + awk->parse.id.block = PARSE_FUNCTION; if (__parse_function (awk) == XP_NULL) return XP_NULL; } else if (MATCH(awk,TOKEN_BEGIN)) { - awk->parse.id.block = PARSE_BLOCK_BEGIN; + awk->parse.id.block = PARSE_BEGIN; + if (__get_token(awk) == -1) return XP_NULL; + + if ((awk->opt.parse & XP_AWK_BLOCKLESS) && + (MATCH(awk,TOKEN_NEWLINE) || MATCH(awk,TOKEN_EOF))) + { + /* when the blockless pattern is supported + * BEGIN and { should be located on the same line */ + PANIC (awk, XP_AWK_EBEGINBLOCK); + } + + if (!MATCH(awk,TOKEN_LBRACE)) PANIC (awk, XP_AWK_ELBRACE); + + awk->parse.id.block = PARSE_BEGIN_BLOCK; if (__parse_begin (awk) == XP_NULL) return XP_NULL; } else if (MATCH(awk,TOKEN_END)) { - awk->parse.id.block = PARSE_BLOCK_END; + awk->parse.id.block = PARSE_END; + if (__get_token(awk) == -1) return XP_NULL; + + if ((awk->opt.parse & XP_AWK_BLOCKLESS) && + (MATCH(awk,TOKEN_NEWLINE) || MATCH(awk,TOKEN_EOF))) + { + /* when the blockless pattern is supported + * END and { should be located on the same line */ + PANIC (awk, XP_AWK_EENDBLOCK); + } + + if (!MATCH(awk,TOKEN_LBRACE)) PANIC (awk, XP_AWK_ELBRACE); + + awk->parse.id.block = PARSE_END_BLOCK; if (__parse_end (awk) == XP_NULL) return XP_NULL; } else if (MATCH(awk,TOKEN_LBRACE)) { /* patternless block */ - awk->parse.id.block = PARSE_BLOCK_ACTION; + awk->parse.id.block = PARSE_ACTION_BLOCK; if (__parse_pattern_block ( awk, XP_NULL, xp_false) == XP_NULL) return XP_NULL; } @@ -504,7 +531,7 @@ static xp_awk_t* __parse_progunit (xp_awk_t* awk) */ xp_awk_nde_t* ptn; - awk->parse.id.block = PARSE_BLOCK_PATTERN; + awk->parse.id.block = PARSE_PATTERN; ptn = __parse_expression (awk); if (ptn == XP_NULL) return XP_NULL; @@ -531,10 +558,9 @@ static xp_awk_t* __parse_progunit (xp_awk_t* awk) (MATCH(awk,TOKEN_NEWLINE) || MATCH(awk,TOKEN_EOF))) { /* blockless pattern */ - xp_bool_t newline = MATCH(awk,TOKEN_NEWLINE); - awk->parse.id.block = PARSE_BLOCK_ACTION; + awk->parse.id.block = PARSE_ACTION_BLOCK; if (__parse_pattern_block ( awk, ptn, xp_true) == XP_NULL) { @@ -554,14 +580,13 @@ static xp_awk_t* __parse_progunit (xp_awk_t* awk) else { /* parse the action block */ - if (!MATCH(awk,TOKEN_LBRACE)) { xp_awk_clrpt (ptn); PANIC (awk, XP_AWK_ELBRACE); } - awk->parse.id.block = PARSE_BLOCK_ACTION; + awk->parse.id.block = PARSE_ACTION_BLOCK; if (__parse_pattern_block ( awk, ptn, xp_false) == XP_NULL) { @@ -586,6 +611,7 @@ static xp_awk_nde_t* __parse_function (xp_awk_t* awk) int n; /* eat up the keyword 'function' and get the next token */ + xp_assert (MATCH(awk,TOKEN_FUNCTION)); if (__get_token(awk) == -1) return XP_NULL; /* match a function name */ @@ -802,10 +828,10 @@ static xp_awk_nde_t* __parse_begin (xp_awk_t* awk) { xp_awk_nde_t* nde; - if (awk->tree.begin != XP_NULL) PANIC (awk, XP_AWK_EDUPBEGIN); - if (__get_token(awk) == -1) return XP_NULL; + xp_assert (MATCH(awk,TOKEN_LBRACE)); - nde = __parse_action (awk); + if (__get_token(awk) == -1) return XP_NULL; + nde = __parse_block(awk, xp_true); if (nde == XP_NULL) return XP_NULL; awk->tree.begin = nde; @@ -816,10 +842,10 @@ static xp_awk_nde_t* __parse_end (xp_awk_t* awk) { xp_awk_nde_t* nde; - if (awk->tree.end != XP_NULL) PANIC (awk, XP_AWK_EDUPEND); - if (__get_token(awk) == -1) return XP_NULL; + xp_assert (MATCH(awk,TOKEN_LBRACE)); - nde = __parse_action (awk); + if (__get_token(awk) == -1) return XP_NULL; + nde = __parse_block(awk, xp_true); if (nde == XP_NULL) return XP_NULL; awk->tree.end = nde; @@ -835,7 +861,9 @@ static xp_awk_chain_t* __parse_pattern_block ( if (blockless) nde = XP_NULL; else { - nde = __parse_action (awk); + xp_assert (MATCH(awk,TOKEN_LBRACE)); + if (__get_token(awk) == -1) return XP_NULL; + nde = __parse_block(awk, xp_true); if (nde == XP_NULL) return XP_NULL; } @@ -865,13 +893,6 @@ static xp_awk_chain_t* __parse_pattern_block ( return chain; } -static xp_awk_nde_t* __parse_action (xp_awk_t* awk) -{ - if (!MATCH(awk,TOKEN_LBRACE)) PANIC (awk, XP_AWK_ELBRACE); - if (__get_token(awk) == -1) return XP_NULL; - return __parse_block(awk, xp_true); -} - static xp_awk_nde_t* __parse_block (xp_awk_t* awk, xp_bool_t is_top) { xp_awk_nde_t* head, * curr, * nde; @@ -3160,8 +3181,8 @@ static xp_awk_nde_t* __parse_next (xp_awk_t* awk) { xp_awk_nde_next_t* nde; - if (awk->parse.id.block == PARSE_BLOCK_BEGIN || - awk->parse.id.block == PARSE_BLOCK_END) + if (awk->parse.id.block == PARSE_BEGIN_BLOCK || + awk->parse.id.block == PARSE_END_BLOCK) { PANIC (awk, XP_AWK_ENEXT); } @@ -3178,8 +3199,8 @@ static xp_awk_nde_t* __parse_nextfile (xp_awk_t* awk) { xp_awk_nde_nextfile_t* nde; - if (awk->parse.id.block == PARSE_BLOCK_BEGIN || - awk->parse.id.block == PARSE_BLOCK_END) + if (awk->parse.id.block == PARSE_BEGIN_BLOCK || + awk->parse.id.block == PARSE_END_BLOCK) { PANIC (awk, XP_AWK_ENEXTFILE); } @@ -3207,13 +3228,14 @@ static int __get_token (xp_awk_t* awk) } while (n == 1); - xp_str_clear (&awk->token.name); awk->token.line = awk->lex.line; awk->token.column = awk->lex.column; if (line != 0 && (awk->opt.parse & XP_AWK_BLOCKLESS) && - awk->parse.id.block == PARSE_BLOCK_PATTERN) + (awk->parse.id.block == PARSE_PATTERN || + awk->parse.id.block == PARSE_BEGIN || + awk->parse.id.block == PARSE_END)) { if (awk->token.line != line) { diff --git a/ase/awk/run.c b/ase/awk/run.c index c2560068..4d10eaf3 100644 --- a/ase/awk/run.c +++ b/ase/awk/run.c @@ -1,5 +1,5 @@ /* - * $Id: run.c,v 1.158 2006-08-03 09:53:45 bacon Exp $ + * $Id: run.c,v 1.159 2006-08-03 15:49:37 bacon Exp $ */ #include @@ -458,6 +458,7 @@ static int __run_main (xp_awk_run_t* run) blk = (xp_awk_nde_blk_t*)run->awk->tree.begin; xp_assert (blk->type == XP_AWK_NDE_BLK); + run->active_block = blk; run->exit_level = EXIT_NONE; if (__run_block (run, blk) == -1) n = -1; } @@ -474,6 +475,7 @@ static int __run_main (xp_awk_run_t* run) blk = (xp_awk_nde_blk_t*)run->awk->tree.end; xp_assert (blk->type == XP_AWK_NDE_BLK); + run->active_block = blk; run->exit_level = EXIT_NONE; if (__run_block (run, blk) == -1) n = -1; } @@ -619,6 +621,7 @@ static int __run_pattern_block (xp_awk_run_t* run, xp_awk_chain_t* chain) if (ptn == XP_NULL) { /* just execute the block */ + run->active_block = blk; if (__run_block (run, blk) == -1) return -1; } else @@ -635,6 +638,7 @@ static int __run_pattern_block (xp_awk_run_t* run, xp_awk_chain_t* chain) if (xp_awk_valtobool(v1)) { + run->active_block = blk; if (__run_block (run, blk) == -1) { xp_awk_refdownval (run, v1); @@ -659,6 +663,7 @@ static int __run_pattern_block (xp_awk_run_t* run, xp_awk_chain_t* chain) if (xp_awk_valtobool(v1)) { + run->active_block = blk; if (__run_block (run, blk) == -1) { xp_awk_refdownval (run, v1); @@ -678,6 +683,7 @@ static int __run_pattern_block (xp_awk_run_t* run, xp_awk_chain_t* chain) if (v2 == XP_NULL) return -1; xp_awk_refupval (v2); + run->active_block = blk; if (__run_block (run, blk) == -1) { xp_awk_refdownval (run, v2); @@ -1164,7 +1170,6 @@ static int __run_continue (xp_awk_run_t* run, xp_awk_nde_continue_t* nde) static int __run_return (xp_awk_run_t* run, xp_awk_nde_return_t* nde) { - if (nde->val != XP_NULL) { xp_awk_val_t* val; @@ -1212,19 +1217,33 @@ static int __run_exit (xp_awk_run_t* run, xp_awk_nde_exit_t* nde) static int __run_next (xp_awk_run_t* run, xp_awk_nde_next_t* nde) { - /* TODO: trigger an error if "next" is called from BEGIN or END */ + /* the parser checks if next has been called in the begin/end + * block or whereever inappropriate. so the runtime doesn't + * check that explicitly */ + + if (run->active_block == (xp_awk_nde_blk_t*)run->awk->tree.begin || + run->active_block == (xp_awk_nde_blk_t*)run->awk->tree.end) + { + PANIC_I (run, XP_AWK_ENEXTCALL); + } + run->exit_level = EXIT_NEXT; return 0; } static int __run_nextfile (xp_awk_run_t* run, xp_awk_nde_nextfile_t* nde) { -/* TODO: trigger an error if "nextfile" is called from BEGIN or END */ /* TODO: some extentions such as nextfile "in/out"; * what about awk -i in1,in2,in3 -o out1,out2,out3 ? */ int n, errnum; + if (run->active_block == (xp_awk_nde_blk_t*)run->awk->tree.begin || + run->active_block == (xp_awk_nde_blk_t*)run->awk->tree.end) + { + PANIC_I (run, XP_AWK_ENEXTFILECALL); + } + n = xp_awk_nextextio_read ( run, XP_AWK_IN_CONSOLE, XP_T(""), &errnum); if (n == -1) diff --git a/ase/test/awk/t25.awk b/ase/test/awk/t25.awk index 85e9a7a9..c14c928d 100644 --- a/ase/test/awk/t25.awk +++ b/ase/test/awk/t25.awk @@ -10,4 +10,4 @@ print /ABC/ ~ /DEF/; } -/zzz/ \ No newline at end of file +/zzz/ diff --git a/ase/test/awk/t26.awk b/ase/test/awk/t26.awk new file mode 100644 index 00000000..b1b8b7db --- /dev/null +++ b/ase/test/awk/t26.awk @@ -0,0 +1,13 @@ +function call_next () +{ + next; +} + +BEGIN { + //call_next (); +} + +END { + call_next (); +} +